周 开,倪 伟
(淮阴工学院 电子与电气工程学院,江苏 淮安 223003)
基于Qt/E的嵌入式Linux GUI研究与实现
周 开,倪 伟*
(淮阴工学院 电子与电气工程学院,江苏 淮安 223003)
随着嵌入式系统在移动通信、手持设备、智能终端和工业控制等领域的广泛应用,嵌入式图形用户接口(Graphical User Interface, GUI )日益成为研究的重点。介绍几种嵌入式GUI的体系框架及其特点,并研究了Qt/Embedded的窗口系统、帧缓存以及信号和槽与事件模型;结合MINI2440开发板提供Qt/Embedded的移植过程、SQL数据库支持的方法。
嵌入式系统;GUI;Qt/Embedded
Huai'an Jiangsu 223003, China)
Abatract: As the development of embedded system in mobile communication, portable devices, smart terminal, industrials control and other fields, embedded Graphical User Interface has increasingly become the focus of research. Several kinds of embedded GUI frameworks and its characteristics were introduced in this paper, and its window system, frame buffer, signals and slots mechanism, and event model were studied. Finally, Qt/Embedded migration process, database support methods based on MINI2440 development board were provided.
GUI是当今计算机发展的重大成就,它为用户提供了友好便利的界面,大大地方便了普通用户的使用,使得用户从繁琐的操作中解脱出来,通过窗口、菜单等方便地完成预设工作[1]。
随着嵌入式系统的智能化发展,GUI的地位也越来越重要,但是不同于桌面系统,嵌入式GUI要求简单、直观、可靠、占用资源小且反应快速,应具备高度可移植性和可裁剪性,以适应系统有限的硬件资源和不同应用环境的需求。
目前,在嵌入式Linux系统中,常用的GUI有MicroWindows、MiniGUI、Qt/Embedded等。
1.1 MicroWindows
MicroWindows由美国CenturySoftware公司开发的开放源代码嵌入式GUI解决方案,它基于典型Server/Client体系结构[1],其体系结构如图1所示。MicroWindows提供了较为完善的图形功能,使用C语言开发,移植性较强。
图1 MicroWindows体系结构
最底层是面向图形显示和键盘、鼠标、触摸屏的驱动程序;中间层提供底层硬件的抽象接口,并完成窗口管理;最高层分别提供兼容X Window和ECMA APIW(Win32子集)的API。其中Nano-X API接口与X接口兼容,但是该接口没有提供窗口管理,如窗口移动和窗口剪切等高级功能,系统需要先启动Nano-X的Server程序Nanox-Server和窗口管理程序Nanowm。Client程序连接Nano-X的Server程序获得自身的窗口绘制操作。ECMA APIW接口与Windows接口兼容,该接口的应用程序无须Nanox-Server和Nanowm,可直接管理窗口。
1.2 MiniGUI
MiniGUI是北京飞漫软件开发的开源Linux轻量级图形界面支持系统,其体系框架如图2所示。其代码全部采用C语言开发,提供完备的多窗口机制和消息传递机制[3]。
图2 MiniGUI体系框架
MiniGUI分为最底层的图形抽象层(Graphics Abstraction Layer,GAL)和输入抽象层(Input Abstraction Layer,IAL),上层为基于标准POSIX接口pthread库的Mini-thread架构和基于Server/Client的Mini-Lite架构。Mini-thread架构用于系统功能较为单一的场合;Mini-Lite架构应用于多进程的应用场合,可实现多进程间的窗口管理、Z序剪切等。
1.3 Qt/Embedded
Qt/Embedded,下文简称为Qt/E,是Trolltech公司开发的面向嵌入式系统的Qt版本,不同平台上的Qt架构为开发者提供了相同的API,所以应用程序移植时只需要重新编译代码而不需要对代码进行修改,Qt/E和Qt/X11的体系结构如图3所示。它支持跨平台,代码采用C++编写,为开发者提供清晰的框架,模块化可裁剪,非常适合嵌入式系统的“小而快”的要求。
图3 Qt/E和Qt/X11体系结构
Qt/E与QT/X11的最大区别是,Qt/E在底层摒弃了Xlib库,直接访问帧缓存frame-buffer作为底层图形接口[4],而QT/X11则需要X-Windows服务器和Xlib库的支持。Qt/E将外部输入设备抽象为按键、鼠标输入事件,底层接口支持按键、鼠标、触摸屏,以及用户自定义的设备等。
2.1 Qt/Embedded窗口系统
Qt/E的窗口系统采用一种Client/Server体系结构,如图4所示。一个Qt/E窗口系统一般包括:一个Server进程、一个或多个Client进程(下面简称为服务器和客户端)。服务器负责为客户端和本身分配显示区域,生成鼠标、按键等事件。而客户端则通过共享内存的进程通信方式与服务器通信申请显示区域,接收鼠标、按键等事件。
图4 Qt/E窗口系统体系结构
2.2 Qt/Embedded帧缓存
Qt/E的底层图形引擎基于帧缓存(frame-buffer),它是标准显示设备驱动接口[5]。帧缓存是一个提供显示内存和显示芯片寄存器从物理内存映射到进程地址空间的设备,通过帧缓存设备可以直接对显存进行读写操作,而不必关心物理显存的位置及换页机制等具体细节。
帧缓存驱动程序的实现分为两方面,一方面是对LCD等相关硬件及缓存的初始化,包括图形缓冲区的创建和设置DMA通道;另一方面是对图形缓冲区的读写操作,read、write及seek等系统调用可以调用驱动程序的读写函数。至于将图形缓冲区的内容输出到LCD显示屏上,则由硬件自动完成,在设置DMA通道和图形缓冲区后,DMA将缓冲区中的内容不断刷新到LCD上,实现图形的显示工作。
在Qt/Embedded中,Qscreen类是抽象出的底层显示设备基类。Qscreen类及其派生类包裹了Qt/E绘制所用的帧缓冲,为旋转帧缓冲内容提供了坐标映射支持,管理framebuffer和调色板。它声明了显示设备的基本描述和操作方式,如打开、关闭、获得显示能力及创建QGfx操作对象等。基类QGfx抽象出显示设备的具体操作接口(图形设备环境),如选择画刷、画线及alpha操作等。
2.3 信号和槽机制及事件模型
当一个特定事件发生或一个对象状态发生变化时,常常需要完成相应的系统响应。Qt系统自行定义的信号和槽机制,以替代其他GUI解决方案中常采用的回调函数与消息映射机制来完成对象间的通信[6],它以进程间通信速率为代价提高通信的简便和灵活性,该机制是Qt的一个重要特征。实现信号和槽机制,必须借助于MOC(Meta Object Compiler),其本质是C++预处理程序,为高层次的时间处理自动生成所需要的附加代码。
当某个信号对其客户或所有者发生的内部状态发生变化时,信号被某一个对象发射,与之相关联的槽将立刻执行。信号和槽机制完全独立于任何事件循环,只有所有与发射信号相关联的槽函数返回以后发射函数(emit)方才返回,这些槽函数将会以随机、不确定顺序逐一执行,开发者不可指定其执行顺序。从形式上讲,信号的声明与普通的C++函数相同,却没有函数体定义,信号的返回类型都是void,不能从信号返回有用信息,槽函数的声明与定义与普通函数相同。
在Qt系统中,事件被封装成继承自抽象类QEvent对象。事件来自于按键、鼠标、触摸屏等硬件输入设备,QTimerEvent等类对象,以及用户自定义等三方面。Qt系统对这些事件一视同仁,Qt的主事件循环从事件队列中获取事件,并将其转化为QEvents类型事件,使用函数QApplication::notify发送转换的事件给相应的对象QObjects。QObjects通过调用其成员函数QObject::event()接收事件,开发者也可以重新实现event函数,在事件到达特定的事件处理器完成事件的处理。
Qt系统中,事件机制是非阻塞的,事件产生方不需要事件响应完成后方才继续后续任务,所以事件支持对象间异步通信。在单线程应用中,因为信号的释放是阻塞的,一定要等到槽函数返回后通信,信号发射函数方才返回,所以信号和槽是一种对象间的同步通信机制。是否支持异步调用是事件机制与信号和槽机制的最本质区别。但从Qt4开始,信号和槽机制被扩展为可以支持跨线程的连接,至此,信号和槽才支持跨线程间的异步调用[7]。
在实际应用中,碍于嵌入式平台体积小、硬件资源有限等特点,需要对Qt/Embedded进行必要的移植和功能上的裁剪,以适应不同需求。限于篇幅关系,本文仅给出Qt/E的移植和SQL数据库移植,也只列出最关键的配置步骤。
3.1 Qt/Embedded的移植
由于Qt/Embedded和Qt/X11有同样的API,通常在宿主机上开发嵌入式系统的应用程序,利用qvfb工具模拟嵌入式平台上的GUI运行环境[8],调试完成后,使用交叉编译工具arm-linux-gcc编译,再移植到嵌入式平台上运行,这样大大提高了GUI开发速率。
在宿主机上搭建Qt/Embedded环境,需要下载、解压软件包tmake-1.13.tar.gz、qt-embedded-2.3.7.tar.gz和qt-x11-2.3.2.tar.gz,并完成相关环境变量的设置和使用configure命令分别配置各个软件包的Makefile文件[9]。
安装tmake软件包:
export TMAKEDIR=$PWD/tmake-1.11
export TMAKEPATH=$TAMEDIR/lib/qws/linux-x86-g++
export PATH=$TMAKEDIR/bin:$PATH
安装Qt/Embedded软件包:
export QTDIR=$PWD
export QTEDIR=$QTDIR
export PATH=$QTDIR/bin:$PATH
export LD_LIBRARY_PATH=$QTDIR/lib:$LD_LIBRARY_PATH
./configure -qconfig local -qvfb -depths 4,8,16,32
make
安装Qt/X11:
export PATH=$PWD/bin:$PATH
./configure -no-opengl
make
在配置qt-embedded时,可以在参数中添加-system -jpef fig等,使平台支持jpeg,gif格式的图形,但也增加了qt-embedded库的大小。
3.2 SQL数据库移植
Qt为数据库访问提供的QtSq模块实现了数据库与Qt应用程序的无缝集成,为开发人员提供了一套与平台和数据库类型无关的调用接口,它由驱动层、SQL接口层和用户接口层等三部分组成。为使嵌入式GUI系统能够完美支持数据库系统,需要移植数据库驱动。首先从Sqlite官网下载最新的源码包,使用交叉编译工具完成编译和安装。执行以下命令:
./configure --prefix=DIR --host=arm-linux
make
make install
将DIR路径下的bin文件夹拷贝到嵌入式系统文件根目录下的/usr/bin文件夹中将lib文件夹拷贝到/lib文件夹中。至此,嵌入式系统完美实现了对Sqlite数据库的支持。
近年来,嵌入式产品的广泛应用带动了GUI的迅速发展,嵌入式系统需要一个高性能、高可靠性的GUI解决方案。Qt/Embedded延续了Qt在桌面系统的所有功能,其丰富的API接口和基于组建的编程模型,使得嵌入式Linux系统应用程序的开发更加便捷,其必将成为未来嵌入式系统的主流GUI。
[1] 游燕珍,赵国锋,徐川.基于Qt/E的嵌入式GUI的研究及其移植[J].微计算机信息, 2008,24(52):61-63.
[2] 谢长生,龚文京,徐君明.基于MicroWindows的嵌入式GUI的分析及应用[J].计算机工程与科学, 2005,27(6):35-37.
[3] 祁献鹏,郭玉东.MiniGUI—面向嵌入式系统的GUI系统[J].信息工程大学学报,2001,2(3):9-11.
[4] 吴子平.基于QTE的嵌入式GUI技术研究与实现[D].荆州:长江大学,2011.
[5] 倪继利.Linux操作系统及Qt窗口设计[M].北京:电子工业出版社,2006.
[6] Jasmin Blanchette,Mask Summerfield.C++ GUI Programming with Qt4[M].北京:电子工业出版社, 2007.
[7] 吴迪.零基础学Qt4编程[M].北京:北京航空航天大学出版社,2010.
[8] 汤伟, 李强.Qt/E的嵌入式Linux GUI研究与实现[J].计算机应用与软件,2011, 28(10):261-263.
[9] 韦东山.嵌入式Linux应用开发完全手册[M].北京:人民邮电出版社,2008.
(责任编辑:尹晓琦)
Research and Implementation of Embedded Linux GUI Base on Qt/E
ZHOU Kai, NI Wei*
(Faculty of Electrical and Electronic Engineering, Huaiyin Institute of Technology,
embedded system; GUI; Qt/Embedded
2015-03-24
国家青年科学基金项目(61203056)
周开(1990-),男,江苏邳州人,在读硕士,主要从事控制理论与控制工程研究;*为通讯作者。
TP316
A
1009-7961(2015)03-0010-04