14 KiB
Inter-Process Communication and Asynchronous Event Process
In this chapter, we introduce how application processes asynchronous event, and
how it implements the inter-process communication by using APIs provided by
MiniGUI.
Asynchronous Event Process
Usually the programming interfaces provided by a GUI system mainly focus on
windowing, messaging, and graphics device. However, a GUI usually provides its
own mechanism while processing system events and such mechanism is always
incompatible with the one provided by operating system itself. The structure of
an application is usually message-drive corresponding to the message loop
mechanism of MiniGUI. In other words, application works through passively
receiving messages. If application needs to actively monitor certain system
events, for example, in UNIX operating system, it can call select system call
to monitor if a certain file descriptor has readable data. We need combine the
message queue mechanism of MiniGUI and other existed mechanisms of OS, in order
to provide a consistent mechanism for application. We will illustrate several
methods to resolve this problem in the chapter.
As we know, there is only one message queue in an application running on
MiniGUI-Processes. Application will create a message loop after being
initialized, and then continuously get messages from this queue until receiving
message MSG_QUIT. When the window procedure of the application handles a
message, it should immediately returns after having handled the message in
order to have a chance to get other messages and handle them. If an application
calls select to listen in a certain file descriptor, it is possible to
encounter a problem: as select system call may cause long-time block, and those
events sent to the application by the MiniGUI-Processes serve will not be
processed in time. Therefore, the way of message driving and select system call
is difficult to be well integrated. In MiniGUI-Threads, each thread has its
own corresponding message queue, while system message queue is managed by
solely performed desktop thread. Therefore, the threads created by any
application can be long-time blocked and can call select like system calls.
However, in MiniGUI-Processes, if you need to listen in a file descriptor
event in one application, you must handle it correctly to avoid the block.
Under MiniGUI-Processes, we have some ways of resolving this problem:
- When calling select system call, pass the value of timeout to ensure select system call will not be long-time blocked.
- Using timer. When the timer is expired, you can use select system call to check the listened file descriptor. If there is not any event occurring, it will return immediately, otherwise perform read or write operation.
- Using function
RegisterListenFDprovided byMiniGUI-Processesto register a listened file descriptor. When a desired event occurs,MiniGUI-Processeswill send messageMSG_FDEVENTto a certain window.
As the former two solutions are comparatively simple, here we will focus on the
third solution. MiniGUI-Processes provides the following functions and one
macro to application:
- Macro
MAX_NR_LISTEN_FDdefines the maximal number of file descriptors that can be listened by MiniGUI. The default value is 5. RegisterListenFDregisters a file descriptor that needs to be listened. You should specify the event type (the argument of type can be one ofPOLLIN,POLLOUT,orPOLLERR),the context information, and the window handle receiving the messageMSG_FDEVENT.UnregisterListenFDunregisters a registered listening file descriptor.
After application uses RegisterListenFD function to register a listening file
descriptor, MiniGUI will send a message of MSG_FDEVENT to the specified
window when the specified event occurs on the descriptor. Application can
handle this message in the window procedure. Libvcongui of MiniGUI uses the
above function to listen to the readable event coming from the master pseudo
terminal, seen as follows (vcongui/vcongui.c):
We can see the use of RegisterListenFD in the following section. Obviously, a
MiniGUI-Processes program can conveniently use the bottom message mechanism
to finish the process of asynchronous event by using this simple interface of
registering listening file descriptor.
MiniGUI-Processes and Inter-Process Communication
As we know, MiniGUI-Processes uses UNIX domain sockets to realize the
interaction between client programs and the server. Application also can use
this mechanism to finish its own communicating task – send a request from
client, while the serve will process the request and send back the response. On
one hand, in the MiniGUI-Processes serve program, you can extend this
mechanism to register your own request processing functions to implement your
request-response communicating task. On the other hand, MiniGUI-Processes
also provides some wrap functions used to create and operate UNIX domain
sockets. Any application under MiniGUI-Processes can create UNIX domain
sockets and finish the data exchange with other MiniGUI-Processes
applications. This chapter will describe how to use the functions provided by
MiniGUI-Processes to finish such kind of communication. Before introducing
the certain interface, let’s first to understand the multi-process
communication model and communication between the server and the clients under
MiniGUI-Processes.
Multi-Process Model under MiniGUI-Processes
MiniGUI-Processes is a multi-process system with C/S architecture. Only one
server program is running during the life cycle. The global variable mgServer
in the server is set to TRUE; the other MiniGUI applications are clients,
mgServer is set to FALSE. Each application runs in different process space,
seen as Figure 1.
<img src="%ATTACHURLPATH%/16.1.jpeg" alt="16.1.jpeg" ALIGN="CENTER" />
Figure 1 Multi-process model of MiniGUI-Processes
The current program structure allows each process to have its own (virtual)
desktop and message queue. The process communication model includes data
exchange realized by shared memory and the client/server communication model
realized by UNIX domain sockets.
Simple Request/Response Processing
MiniGUI-Processes uses UNIX domain socket to communicate between the server
and the clients. In order to facilitate such communication, MiniGUI-Processes
introduces a simple request/response mechanism. Clients send request to the
server through a specific structure; the server handles the request and
responds. At the end of clients, a request is defined as follows
(minigui/minigui.h):
Here, id is an integer used to identify the request type; data is the data
associated to the request; len_data is the length of the data in bytes. After
initializing a REQUEST structure, clients can call ClientRequest to send
the request to the server, and wait for the response from the server. The
prototype of this function is as follows:
The server program (mginit) can get all client requests during its own message
loop; it will process each request and send the final result to the client. The
server can call ServerSendReply to send the reply to the client:
In the above simple C/S communication, the clients and the serve must be accord with each other for a certain request type, that is, the clients and the server must understand each type of data and process it properly.
MiniGUI-Processes uses the above way to realize most of system-level
communication tasks:
- Mouse cursor management. Mouse cursor is a global resource. When you create or destroy it, change the shape or position of it, or show or hide it, you should send a request to the server. The server will finish the task and reply the result to you.
- Layer management. When a client checks the information of layers, creates new layer, joins a certain existed layer, or delete a layer, it sends a request to the server.
- Window management. When a client creates, destroy, and move a main window, it sends a request to the server.
- Other system-level works. For example, in new
GDIinterfaces, the server manages the video memory of the video adapter. When clients need create the memoryDCin video memory, they will send a request to the server. In order to allow application to simply implement the communication between clients and the server by using the mechanism above, you can register some customized request process functions in the server, and then clients can send requests to the server.MiniGUI-Processesprovides the following interfaces to the server:
The server can register a request handler by calling RegisterRequestHandler.
Note that the prototype of request handler is defined by REQ_HANDLER. MiniGUI
has also defined two macros: MAX_SYS_REQID and MAX_REQID. MAX_REQID is
the maximum request identifier that can be registered; while MAX_SYS_REQID
does MiniGUI use the maximum request identifier internally. In other words, the
request identifier registered by RegisterRequestHandler must be larger than
MAX_SYS_REQID and less than or equal to MAX_REQID.
We assume that the server calculates the sum of two integers for clients. Clients send two integers to the server, while the server sends the sum of two integers to the clients. The following program runs in the server program and registers a request handler in the system:
Client can send a request to the server to get the sum of two integers by using the following program:
By using this simple request/response technology, MiniGUI-Processes can
create a convenient inter-process communication mechanism between the clients
and the server. However, this technology also has some shortcomings, for
example, the number of request is limited by the value of MAX_REQID, the
communication mechanism is not flexible, and the request can only be sent to
the server (mginit) of MiniGUI-Processes from the clients.
Wraps for UNIX Domain Socket
In order to solve the problem of above simple request/reply mechanism,
MiniGUI-Processes also provides some wrap functions for UNIX domain socket.
The prototypes of these functions are as follow (minigui/minigui.h):
The above functions are used to create UNIX domain socket and perform data
transfer. They are the wraps of basic socket function provided by the operating
system. The uses of these functions are described as follow:
serv_listen:The server calls this function to create a listening socket and returns socket file descriptor. It is suggested to create server listening socket under the directory of /var/tmp/.serv_accept:The server calls this function to accept the connection request from clients.cli_conn:Client calls this function to connect the server. Name is the listening socket of the server. The socket created for the client is stored in the directory of /var/tmp/, named with -c, in which c is used to differentiate the purpose of different socket communication task, and specified by the argument of project.MiniGUI-Processesinternally uses a, so the sockets created by application program should use alphabets excluding a.sock_write_t:After creating the connection, client and server can usesock_write_tandsock_read_tto perform data exchange. Arguments ofsock_write_tare similar to system call write, but can pass a timeout value in the unit of 10ms. When the argument is zero, the timeout is disabled. Note that timeout setting is only valid in the program mginit.sock_read_t:Arguments ofsock_read_tare similar to system call read, but can pass a timeout value in the unit of 10ms. When the argument is zero, the timeout is disabled. Note that timeout setting is only valid in program mginit.
The following code illustrates how a server program creates a listening socket by using above functions:
When the server receives the client connection request, the window of hwnd will
receive message MSG_FDEVENT, then the server can accept this connection
request:
In the above code, the server registers the connected file descriptor as
listening descriptor. Therefore, when handling message MSG_FDEVENT, the
server should determine the file descriptor type that causes message
MSG_FDEVENT.
Client can use the following code to connect to the server:
-- Main.XiaodongLi - 06 Nov 2009
<< | Table of Contents | >>