📄 minigui体系结构之一 体系结构概览.htm
字号:
pthread_mutex_unlock (&pMsgQueue->lock);
</PRE></TD></TR></TBODY></TABLE>
<P>信号量 wait 用来同步消息循环。一般来说,一个线程在建立窗口之后,要进入消息循环持续地从消息队列中获取消息(通过 GetMessage()
函数)。当消息队列中没有任何消息时,该线程将进入休眠状态,而当其他线程将消息邮寄或发送到该消息队列之后,将通过信号量 wait 唤醒该线程:</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> sem_getvalue (&pMsgQueue->wait, &sem_value);
if (sem_value == 0)
sem_post(&pMsgQueue->wait);
</PRE></TD></TR></TBODY></TABLE>
<P>在 MiniGUI 的消息队列结构中,第一个成员是消息队列的状态字。该状态字通过标志位表示如下状态:</P>
<UL>
<LI>消息队列中是否有邮寄消息;
<LI>消息队列中是否有通知消息;
<LI>消息队列中是否有同步消息;
<LI>消息队列中是否有退出消息;
<LI>消息队列中是否有重绘消息;
<LI>消息队列中是否有定时器消息。 </LI></UL>
<P>通过这些标志,GetMessage()
可判断是否需要检查邮寄消息队列、通知消息链表和同步消息链表等等。同时,利用这些标志还可以处理上面提到的一些特殊消息。这里以定时器为例进行说明。</P>
<P>在 MiniGUI 中,一个创建了窗口的线程一般拥有一个消息队列,使用该消息队列所有窗口,包括子窗口在内,一共可以建立 8
个定时器。这些定时器是否到期,体现在消息队列的状态字上――状态字的最低 8 位分别用来表示这 8
个定时器是否到期。消息队列中同时还有三个成员:</P>
<TABLE class=code-sample cellPadding=0 width="100%" border=0>
<TBODY>
<TR>
<TD><PRE> HWND TimerOwner[8]; // 定时器所有者
int TimerID[8]; // 定时器标识符
BYTE TimerMask; // 已使用的定时器掩码
</PRE></TD></TR></TBODY></TABLE>
<P>其中 TimerMask 表示当前有效的定时器,每位表示一个定时器;TimerID 表示这 8 个定时器的标识符(整数);而
TimerOwner 则表示定时器的所有者(窗口句柄)。这种定时器的实现方法类似 Linux
内核中的信号实现。定时器是否有效以及是否到期均由二进制字节的一个位来表示。当 GetMessage
检查这些标志时发现有某个定时器到期才会获得一个定时器消息。也就是说,定时器消息是不排队的。这样就解决了排队时可能塞满消息队列的问题。</P><A
id=5 name=5></A>
<P><STRONG class=subhead>5 面向对象技术在 MiniGUI 中的应用</STRONG></P><STRONG>5.1
控件类和控件</STRONG>
<P>MiniGUI 中的每个控件都属于某种子窗口类,是对应子窗口类的实例。这类似于面向对象技术中类和对象的关系。图 3 给出了 MiniGUI
中控件和控件类之间的关系。</P>
<P align=center><IMG alt="" src="MiniGUI体系结构之一 体系结构概览.files/image03.gif"
border=0><BR>图 3 控件类和控件之间的关系</P>
<P>每个控件的消息实际都是有该控件所属控件类的回调函数处理的,从而可以让每个属于统一控件类的控件均保持有相同的用户界面和处理行为。</P>
<P>但是,如果我们在调用某个控件类的回调函数之前,首先调用自己定义的某个回调函数的话,我们就可以让该控件重载控件类的某些处理行为,从而让该控件一方面继承控件类的大部分处理行为,另一方面又具有自己的特殊行为。这实际就是面向对象中的继承和派生。比如,一般的编辑框会接收所有的键盘输入,当我们希望自己的编辑框只接收数字时,就可以用这种办法屏蔽非数字的字符输入。</P><STRONG>5.2
GAL 和 IAL</STRONG>
<P>在 MiniGUI 0.3.xx 的开发中,我们引入了图形和输入抽象层(Graphics and Input Abstract
Layer,GAL 和 IAL)的概念。抽象层的概念类似 Linux
内核虚拟文件系统的概念。它定义了一组不依赖于任何特殊硬件的抽象接口,所有顶层的图形操作和输入处理都建立在抽象接口之上。而用于实现这一抽象接口的底层代码称为“图形引擎”或“输入引擎”,类似操作系统中的驱动程序。这实际是一种面向对象的程序结构。利用
GAL 和 IAL,MiniGUI 可以在许多图形引擎上运行,比如 SVGALib 和 LibGGI,并且可以非常方便地将 MiniGUI
移植到其他 POSIX 系统上,只需要根据我们的抽象层接口实现新的图形引擎即可。目前,我们已经编写了基于 SVGALib 和 LibGGI
的图形引擎。利用 LibGGI, MiniGUI 应用程序可以运行在 X Window 上,将大大方便应用程序的调试。我们目前正在进行
MiniGUI 私有图形引擎的设计开发。通过 MiniGUI
的私有图形引擎,我们可以最大程度地针对窗口系统对图形引擎进行优化,最终提高系统的图形性能和效率。</P>
<P>GAL 和 IAL 的结构是一样的,我们这里只拿 GAL 作为实例说明面向对象技术的运用,参见图 4。</P>
<P>系统维护一个已注册图形引擎数组,保存每个图形引擎数据结构的指针。系统利用一个指针保存当前使用的图形引擎。一般而言,系统中至少有两个图形引擎,一个是“哑”图形引擎,不进行任何实际的图形输出;一个是实际要使用的图形引擎,比如
LibGGI 或者 SVGALib。每个图形引擎的数据结构定义了该图形引擎的一些信息,比如标识符、属性等,更重要的是,它实现了 GAL
所定义的各个接口,包括初始化和终止、图形上下文管理、画点处理函数、画线处理函数、矩形框填充函数、调色板函数等等。</P>
<P align=center><IMG alt="" src="MiniGUI体系结构之一 体系结构概览.files/image04.gif"
border=0><BR>图 4 GAL 结构</P>
<P>如果在某个实际项目中所使用的图形硬件比较特殊,现有的图形引擎均不支持。这时,我们就可以安照 GAL 所定义的接口实现自己的图形引擎,并指定
MiniGUI 使用这种私有的图形引擎即可。这种软件技术实际就是面向对象多态性的具体体现。</P>
<P>利用 GAL 和 IAL,大大提高了 MiniGUI 的可移植性,并且使得程序的开发和调试变得更加容易。我们可以在 X Window
上开发和调试自己的 MiniGUI 程序,通过重新编译就可以让 MiniGUI 应用程序运行在特殊的嵌入式硬件平台上。</P><STRONG>5.3
字符集和字体支持</STRONG>
<P>在成功引入 GAL 和 IAL 之后,我们又在处理字体和字符集的模块当中引入了逻辑字体的概念。逻辑字体是 MiniGUI
用来处理文本(包括文本输出和文本分析)的顶层接口。逻辑字体接口将各种不同的字体(比如宋体、黑体和揩体)和字体格式(比如等宽字体、变宽字体等光栅字体和
TrueType
等矢量字体),以及各种不同字符集(ISO-8859、GB2312、Big5、UNICODE等)综合了起来,从而可以通过统一的接口显示不同字符集的不同字体的文本,并且还可以分析各种字符集文本的组成,比如字符、单词等。在多字体和多字符集的支持中,我们也采用了面向对象的软件技术,使得添加新的字体支持和新的字符集支持非常方便。目前,MiniGUI
能够支持各种光栅字体和 TrueType、Adobe Type 1 等矢量字体,并能够支持 GB2312、Big5 等多字节字符集,UNICODE
的支持正在开发当中。</P>
<P>相对 GAL 和 IAL 而言,MiniGUI
中的字符集和字体支持更加复杂,涉及到的内容也较多。前面提到,我们通过逻辑字体这一接口,实现了文字输出和文本分析两个功能。实际这两个功能是相互关联的。在进行文本输出时,尤其在处理多字节字符集,比如
GB2312 或者 Big5 时,首先要对文本进行分析,以便判断是否是一个属于该字符集的双字节字符。</P>
<P>图 5 给出了逻辑字体、设备字体以及字符集之间的关系。</P>
<P align=center><IMG alt="" src="MiniGUI体系结构之一 体系结构概览.files/image05.gif"
border=0><BR>图 5 逻辑字体以及相关数据结构</P><A id=6 name=6></A>
<P><STRONG class=subhead>6 在 MiniGUI 2.0 中的考虑</STRONG></P>
<P>尽管 MiniGUI 采用多线程机制实现了一个小巧、高效的窗口系统,但有很多理由希望 MiniGUI
能够采用多进程机制实现(尽管多进程机制可能带来通讯上的额外开支):</P>
<UL>
<LI>良好的地址保护。窗口本身的崩溃不会影响 MiniGUI 的运行,而目前的多线程机制无法提供地址保护。
<LI>信号处理上的问题。在多线程程序中,所有的多线程共享同一个信号处理方式,包括是否忽略、是否捕获等等。这对某些大型软件是很难接受的。
<LI>多线程程序对程序员要求较高。在编写多线程程序时,通常要考虑到函数的“线程安全”问题,即函数是否是可重入的,因此,我们通常不能使用全局或者静态变量。
</LI></UL>
<P>鉴于上述需求,我们将在接下来的 MiniGUI 2.0
开发中,进行一些体系结构上的调整,其中最为重要的就是采用进程机制替代线程机制。</P><A id=resources
name=resources></A>
<P><STRONG class=subhead>参考资料</STRONG></P>
<UL>
<LI><B>POSIX 及线程资源</B><BR>有关 POSIX 线程的网络资源:
<LI style="LIST-STYLE-TYPE: none">
<UL>
<LI><A href="http://pauillac.inria.fr/~xleroy/linuxthreads/">The
LinuxThreads Library</A> [Xavier Leroy]
<LI><A href="http://www.aa.net/~mtp/PCthreads.html">POSIX .1c and DCE
Threads For Linux</A>
<LI><A
href="ftp://ftp.informatik.uni-erlangen.de/local/cip/mskuhn/misc/linux-posix.1b">A
Vision for Linux 2.2 -- POSIX.1b Compatibility and Real-Time
Support</A>
<LI><A href="http://www.knosof.co.uk/posix.html">POSIX Related Web
Sites</A> </LI></UL>
<LI><B>MiniGUI 资源</B>
<LI style="LIST-STYLE-TYPE: none">
<UL>
<LI><A href="http://www.minigui.org/">MiniGUI 主页</A>
<LI><A href="ftp://ftp.minigui.org/pub/minigui">MiniGUI FTP 站点</A>
</LI></UL>
<LI><B>MiniGUI 邮件列表</B>
<LI style="LIST-STYLE-TYPE: none">
<UL>
<LI>发信:<A
href="mailto:minigui-devel@egroups.com">minigui-devel@egroups.com</A>
<LI>订阅:<A
href="mailto:minigui-devel-subscribe@egroups.com">minigui-devel-subscribe@egroups.com</A>
<LI>解除订阅:<A
href="mailto:minigui-devel-unsubscribe@egroups.com">minigui-devel-unsubscribe@egroups.com</A>
</LI></UL></LI></UL><A id=author name=author></A>
<P><STRONG class=subhead>关于作者</STRONG><BR>魏永明(ymwei@minigui.org),男,27
岁,工学硕士,现任蓝点软件(深圳)有限公司北京研发中心技术主管。国内最有影响的自由软件项目之一-- MiniGUI
的创始人以及主要开发人员。著有《Linux 实用教程》与《学用 Linux 与 Windows NT》,并主持翻译了《Red Hat Linux
奥秘》、《Linux 编程宝典》 等大量优秀的 Linux 技术著作。是清华大学 AKA Linux 编程技术系列讲座的主讲人。</P><!-- table border="1" cellspacing="1" cellpadding="3"> <tr> <td><font face="helvetica,helv,arial" size="-1">trademark or attribution statements (possibly with image) that are required for publishing or reprinting</font> </td> </tr> </table--><!-- End paper --><BR></TD>
<TD vAlign=top width=8><IMG height=1 alt=""
src="MiniGUI体系结构之一 体系结构概览.files/c.gif" width=8></TD></TR>
<TR vAlign=top height=8>
<TD vAlign=top width=8></TD>
<TD vAlign=top width=8></TD>
<TD vAlign=top width=8></TD></TR>
<TR vAlign=top height=8>
<TD vAlign=top width=8><!-- gutter --></TD>
<TD vAlign=top width=8><!-- comments #7: rate article form -->
<TABLE cellSpacing=0 cellPadding=0 width=150 border=0>
<TBODY>
<TR>
<TD width="100%" bgColor=#cc6633 height=3><IMG height=3 alt=""
src="MiniGUI体系结构之一 体系结构概览.files/c.gif" width=150 border=0></TD></TR>
<TR>
<TD width="100%" bgColor=#333333 height=1><IMG height=1 alt=""
src="MiniGUI体系结构之一 体系结构概览.files/c.gif" width=150 border=0></TD></TR>
<TR>
<TD width="100%" bgColor=#000000 height=1><IMG height=1 alt=""
src="MiniGUI体系结构之一 体系结构概览.files/c.gif" width=150 border=0></TD></TR>
<TR>
<TD width="100%" bgColor=#ffffff height=5><IMG height=5 alt=""
src="MiniGUI体系结构之一 体系结构概览.files/c.gif" width=150 border=0></TD></TR>
<TR vAlign=top>
<TD>
<FORM
action=/developerWorks/cn/cnratings.nsf/RateArticle?CreateDocument
method=post><!-- comments #7: paste title here --><INPUT type=hidden
value="MiniGUI体系结构之一 体系结构概览" name=ArticleTitle> <!-- comments #7: paste zone here --><INPUT type=hidden value=Linux
name=Zone> <INPUT type=hidden value=简体中文 name=region> <INPUT
type=hidden value=/developerWorks/cn/thankyou/feedback-linux.html
name=RedirectURL> <FONT face=helvetica,helv,arial
size=-1><B>您对这篇文章的看法如何?</B></FONT>
<P></P>
<TABLE cellSpacing=0 cellPadding=0 width=570 border=0>
<TBODY>
<TR vAlign=top>
<TD><INPUT type=radio value=5 name=Rating><FONT
face=helvetica,helv,arial size=-1>真棒!</FONT></TD>
<TD><INPUT type=radio value=4 name=Rating><FONT
face=helvetica,helv,arial size=-1>好文章</FONT></TD>
<TD><INPUT type=radio value=3 name=Rating><FONT
face=helvetica,helv,arial size=-1>一般,尚可</FONT></TD>
<TD><INPUT type=radio value=2 name=Rating><FONT
face=helvetica,helv,arial size=-1>需提高</FONT></TD>
<TD><INPUT type=radio value=1 name=Rating><FONT
face=helvetica,helv,arial
size=-1>太差!</FONT></TD></TR></TBODY></TABLE><BR><FONT
face=helvetica,helv,arial size=-1><B>评价</B></FONT><BR><TEXTAREA name=Comments rows=3 wrap=virtual cols=52></TEXTAREA><BR><BR><INPUT type=submit value=提交反馈意见></FORM></TD></TR></TBODY></TABLE><!-- end rate article form --></TD>
<TD vAlign=top width=8></TD></TR>
<TR vAlign=top height=8>
<TD vAlign=top width=8></TD>
<TD vAlign=top width=8></TD>
<TD vAlign=top
width=8></TD></TR></TBODY></TABLE><!-- end content --><BR><BR>******>> An
error has occurred while processing a Server Side Include file
<BR><BR></BODY></HTML>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -