Download (direct link):
Servers can also be used to provide asynchronous services because they run in a separate thread to their clients. Most of the system services on Symbian OS, particularly those providing asynchronous functionality, are provided using the client-server framework: for example the window server (for access to UI resources such as the screen and keypad), the serial communications server (for access to the serial ports) and the telephony server.
11.2 How Do the Client and Server Fit Together?
A Symbian OS server always runs in a separate thread to its clients and often runs in a separate process. All interaction is performed by message passing or inter-thread data transfer.
1 A synchronous function performs a service then returns directly to the caller, often returning an indication of success or failure. A typical example of a synchronous function is a call to format a descriptor or to copy the contents of one descriptor into another.
An asynchronous function submits a request as part of the function call and returns to the caller, but completion of that request occurs some time later. Upon completion, the caller receives a signal to notify it and indicate success or failure. A good example of an asynchronous service is a timer - the request completes at a later stage when the wait time has elapsed.
HOW DO THE CLIENT AND SERVER FIT TOGETHER?
This protects the system resource that the server accesses from any badly programmed or malicious clients. A badly-behaved client should not be able to "crash" a server, although, of course, the server must still guard against invalid data or out-of-sequence client requests and, if necessary, panic the client responsible.
A typical server has associated client-side code that formats requests to pass to the server, via the kernel, and hides the implementation details of the private client-server communication protocol.
This means that, for example, a "client" of the Symbian OS file server (efile.exe2) is actually a client of the file server's client-side implementation and links against the DLL which provides it (efsrv.dll), as shown in Figure 11.1.
Calling Client (e.g. test code)
Client-side File Server implementation
Links to efsrv.lib and calls API methods, such as
Client-server communication (kernel-mediated messages)
Figure 11.1 File server, client and calling client
In the rest of this chapter, I'll make it clear when I use the term "client" whether I mean:
• the client-side implementation that communicates directly with the server, or
• code which links to that client-side implementation, using it to request a service of the server, a "calling client".
2 Chapter 13 discusses the difference between executable code which runs on the emulator and on target hardware. In effect, on Windows, Symbian OS runs in a single process which emulates multiple processes by loading them as DLLs into separate threads. Thus, while the file server is built to run on hardware as efile.exe, to run on Windows builds it is built as efile.dll.
THE CLIENT-SERVER FRAMEWORK IN THEORY
The client-side server implementation may also be responsible for starting the server if it is not critical to the system (whereupon it will be started when the operating system itself starts).
11.3 How Do the Client and Server Communicate?
A client and a server run in different threads and often in different processes. When running in different processes, they cannot access each other's virtual address spaces, so they use a message-passing protocol to communicate. The communication channel is known as a session. A session is created by the kernel, which also acts as an intermediary for all client-server communication. A client may have several sessions with a server, although, as I'll explain later, the number of sessions should be kept to a minimum, because each session consumes resources in the kernel and server.
Client-server communication occurs when the client makes a request to the server using a message that identifies the nature of the request and can additionally hold some parameter data. For simple transactions this is sufficient, but for more complex parameters the server can transfer additional data to or from the client thread using inter-thread data transfer functions, which I described in Chapter 10.
In the rest of this chapter, unless I state otherwise, this discussion assumes that the client and server are running in separate processes, which means that data transfer between them requires inter-process communication (IPC). Under these circumstances parameter data can never be transferred using simple C++ pointers, because the server never has direct access to the client's address space (or vice versa). Instead, the kernel performs the data access on the server's behalf.
When the request has been fulfilled, the server notifies the client that it has completed by signaling the client thread's request semaphore, returning a completion result as a 32-bit value.