分享
 
 
 

基于Linux和MiniGUI的嵌入式系统软件开发指南(六)

王朝system·作者佚名  2008-05-19
窄屏简体版  字體: |||超大  

作者:魏永明

MiniGUI 提供的非 GUI/GDI 接口

本文讲述了 MiniGUI 为应用程序提供的非 GUI/GDI 接口,这些接口能够帮助应用程序更好地和操作系统交互,扩展应用程序功能,并提高应用程序的可移植性。内容主要涉及到如下几个方面:MiniGUI-Lite 和 select 系统调用;基于 UNIX Domain Socket 的进程间通讯;编写可移植性代码等。

1 引言

一般而言,GUI 系统的应用程序编程接口主要集中于窗口、消息队列、图形设备等相关方面。但因为 GUI 系统在处理系统事件时通常会提供自己的机制,而这些机制往往会和操作系统本身提供的机制不相兼容。比如,MiniGUI 提供了消息循环机制,而应用程序的结构一般是消息驱动的;也就是说,应用程序通过被动接收消息来工作。但很多情况下,应用程序需要主动监视某个系统事件,比如在 UNIX 操作系统中,可以通过 select 系统调用监听某个文件描述符上是否有可读数据。这样,如何将 MiniGUI 的消息队列机制和现有操作系统的其他机制融合在一起,就成了一个较为困难的问题。本文将讲述几种解决这一问题的方法。

我们知道,MiniGUI-Lite 采用 UNIX Domain Socket 实现客户程序和服务器程序之间的交互。应用程序也可以利用这一机制,完成自己的通讯任务??客户向服务器提交请求,而服务器完成对客户的请求处理并应答。一方面,在 MiniGUI-Lite 的服务器程序中,你可以扩展这一机制,注册自己的请求处理函数,完成定制的请求/响应通讯任务。另一方面,MiniGUI-Lite 当中也提供了若干用来创建和操作 UNIX Domain Socket 的函数,任何 MiniGUI-Lite 的应用程序都可以建立 UNIX Domain Socket,并完成和其他 MiniGUI-Lite 应用程序之间的数据交换。本文将举例讲述如何利用 MiniGUI-Lite 提供的函数完成此类通讯任务。

嵌入式 Linux 系统现在能够在许多不同架构的硬件平台上运行,MiniGUI 也能够在这些硬件平台上运行。但由于许多硬件平台具有和其他硬件平台不同的特性,比如说,常见的 CPU 是 Little Endian 的,而某些 CPU 则是 Big Endian 的。这要求我们在编写代码,尤其是文件 I/O 相关代码时,必须编写可移植代码,以便适合具有不同架构的平台。本文将描述 MiniGUI 为应用程序提供的可移植性函数及其用法。

除了与上述内容相关的函数之外,MiniGUI 还提供了其他一些函数,本文最后部分将描述这些函数的用途和用法,包括配置文件读写以及定点数运算。

2 MiniGUI-Lite和 select 系统调用

我们知道,在 MiniGUI-Lite 之上运行的应用程序只有一个消息队列。应用程序在初始化之后,会建立一个消息循环,然后不停地从这个消息队列当中获得消息并处理,直到接收到 MSG_QUIT 消息为止。应用程序的窗口过程在处理消息时,要在处理完消息之后立即返回,以便有机会获得其他的消息并处理。现在,如果应用程序在处理某个消息时监听某个文件描述符而调用 select 系统调用,就有可能会出现问题??因为 select 系统调用可能会长时间阻塞,而由 MiniGUI-Lite 服务器发送给客户的事件得不到及时处理。这样,消息驱动的方式和 select 系统调用就难于很好地融合。在 MiniGUI-Threads 中,因为每个线程都有自己相应的消息队列,而系统消息队列是由单独运行的 desktop 线程管理的,所以任何一个应用程序建立的线程都可以长时间阻塞,从而可以调用类似 select 的系统调用。但在 MiniGUI-Lite 当中,如果要监听某个应用程序自己的文件描述符事件,必须进行恰当的处理,以避免长时间阻塞。

在 MiniGUI-Lite 当中,有几种解决这一问题的办法:

在调用 select 系统调用时,传递超时值,保证 select 系统调用不会长时间阻塞。

设置定时器,定时器到期时,利用 select 系统调用查看被监听的文件描述符。如果没有相应的事件发生,则立即返回,否则进行读写操作。

利用 MiniGUI-Lite 提供的 RegisterListenFD 函数在系统中注册监听文件描述符,并在被监听的文件描述符上发生指定的事件时,向某个窗口发送 MSG_FDEVENT 消息。

由于前两种解决方法比较简单,这里我们重点讲述的第三种解决办法。MiniGUI-Lite 为应用程序提供了如下两个函数及一个宏:

#define MAX_NR_LISTEN_FD 5

/* Return TRUE if all OK, and FALSE on error. */

BOOL GUIAPI RegisterListenFD (int fd, int type, HWND hwnd, void* context);

/* Return TRUE if all OK, and FALSE on error. */

BOOL GUIAPI UnregisterListenFD (int fd);

MAX_NR_LISTEN_FD 宏定义了系统能够监听的最多文件描述符数,默认定义为 5。

RegisterListenFD 函数在系统当中注册一个需要监听的文件描述符,并指定监听的事件类型(type 参数,可取 POLLIN、POLLOUT 或者 POLLERR),接收 MSG_FDEVENT 消息的窗口句柄以及一个上下文信息。

UnregisterListenFD 函数注销一个被注册的监听文件描述符。

在应用程序使用RegisterListenFD 函数注册了被监听的文件描述符之后,当指定的事件发生在该文件描述符上时,系统会将 MSG_FDEVENT 消息发送到指定的窗口,应用程序可在窗口过程中接收该消息并处理。MiniGUI 中的 libvcongui 就利用了上述函数监听来自主控伪终端上的可读事件,如下面的程序段所示(vcongui/vcongui.c):

...

/* 注册主控伪终端伪监听文件描述符 */

RegisterListenFD (pConInfo-masterPty, POLLIN, hMainWnd, 0);

/* 进入消息循环 */

while (!pConInfo-terminate && GetMessage (&Msg, hMainWnd)) {

DispatchMessage (&Msg);

}

/* 注销监听文件描述符 */

UnregisterListenFD (pConInfo-masterPty);

...

/* 虚拟控制台的窗口过程 */

static int VCOnGUIMainWinProc (HWND hWnd, int message, WPARAM wParam, LPARAM lParam)

{

PCONINFO pConInfo;

pConInfo = (PCONINFO)GetWindowAdditionalData (hWnd);

switch (message) {

...

/* 接收到 MSG_FDEVENT 消息,则处理主控伪终端上的输入数据 */

case MSG_FDEVENT:

ReadMasterPty (pConInfo);

break;

...

}

/* 调用默认窗口过程 */

if (pConInfo-DefWinProc)

return (*pConInfo-DefWinProc)(hWnd, message, wParam, lParam);

else

return DefaultMainWinProc (hWnd, message, wParam, lParam);

}

在 3.2 节当中,我们还可以看到RegisterListenFD 函数的使用。显然,通过这种简单的注册监听文件描述符的接口,MiniGUI-Lite 程序能够方便地利用底层的消息机制完成对异步事件的处理。

3 MiniGUI-Lite 与进程间通讯

3.1 简单请求/应答处理

我们知道,MiniGUI-Lite 利用了 UNIX Domain Socket 实现服务器和客户程序之间的通讯。为了实现客户和服务器之间的简单方便的通讯,MiniGUI-Lite 中定义了一种简单的请求/响应结构。客户程序通过指定的结构将请求发送到服务器,服务器处理请求并应答。在客户端,一个请求定义如下(include/gdi.h):

typedef struct tagREQUEST {

int id;

const void* data;

size_t len_data;

} REQUEST;

typedef REQUEST* PREQUEST;

其中,id 是用来标识请求类型的整型数,data 是发送给该请求的关联数据,len_data 则是数据的长度。客户在初始化 REQUEST 结构之后,就可以调用 cli_request 向服务器发送请求,并等待服务器的应答。该函数的原型如下。

/* send a request to server and wait reply */

int cli_request (PREQUEST request, void* result, int len_rslt);

服务器程序(即 mginit)会在自己的消息循环当中获得来自客户的请求,并进行处理,最终会将处理结果发送给客户。

在上述这种简单的客户/服务器通讯中,客户和服务器必须就每个请求类型达成一致,也就是说,客户和服务器必须了解每种类型请求的数据含义并进行恰当的处理。

MiniGUI-Lite 利用上述这种简单的通讯方法,实现了若干系统级的通讯任务:

鼠标光标的管理。鼠标光标是一个全局资源,当客户需要创建或者销毁鼠标光标,改变鼠标光标的形状、位置,显示或者隐藏鼠标时,就发送请求到服务器,服务器程序完成相应任务并将结果发送给客户。

层及活动客户管理。当客户查询层的信息,新建层,加入某个已有层,或者设置层中的活动客户时,通过该接口发送请求到服务器。

其他一些系统级的任务。比如在新的 GDI 接口中,服务器程序统一管理显示卡中可能用来建立内存 DC 的显示内存,当客户要申请建立在显示内存中的内存 DC 时,就会发送请求到服务器。

为了让应用程序也能够通过这种简单的方式实现客户和服务器之间的通讯,服务器程序可以注册一些定制的请求处理函数,然后客户就可以向服务器发送这些请求。为此,MiniGUI-Lite 提供了如下接口:

#define MAX_SYS_REQID 0x0010

#define MAX_REQID 0x0018

/*

* Register user defined request handlers for server

* Note that user defined request id should larger

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有