Symbian OS Explained - Effective C++ Programming For Smartphones (2005) (779885), страница 38
Текст из файла (страница 38)
On Symbian OS, it is thisrationale which protects the filesystem; all access to file-based data mustbe made through the file server client, efsrv.dll, or a higher-levelcomponent which uses it such as the stream store, estor.dll.Servers can also be used to provide asynchronous services becausethey run in a separate thread to their clients. Most of the system serviceson Symbian OS, particularly those providing asynchronous functionality,are provided using the client–server framework: for example the windowserver (for access to UI resources such as the screen and keypad), theserial communications server (for access to the serial ports) and thetelephony server.11.2How Do the Client and Server Fit Together?A Symbian OS server always runs in a separate thread to its clients andoften runs in a separate process. All interaction is performed by messagepassing or inter-thread data transfer.1A synchronous function performs a service then returns directly to the caller, oftenreturning an indication of success or failure.
A typical example of a synchronous functionis 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 tothe caller, but completion of that request occurs some time later. Upon completion, thecaller receives a signal to notify it and indicate success or failure. A good example of anasynchronous service is a timer – the request completes at a later stage when the wait timehas elapsed.HOW DO THE CLIENT AND SERVER FIT TOGETHER?169This protects the system resource that the server accesses from anybadly programmed or malicious clients.
A badly-behaved client shouldnot be able to ”crash” a server, although, of course, the server muststill guard against invalid data or out-of-sequence client requests and, ifnecessary, panic the client responsible.A typical server has associated client-side code that formats requeststo pass to the server, via the kernel, and hides the implementation detailsof 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), asshown in Figure 11.1.Calling Client(e.g.
test code)Client-side File Serverimplementationmytest.exeLinks to efsrv.lib and callsAPI methods, such asRFs::Connect()efsrv.dllPROCESSBOUNDARYClient−server communication(kernel-mediated messages)File ServerFigure 11.1efile.exeFile server, client and calling clientIn 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 theserver, or• code which links to that client-side implementation, using it to requesta service of the server, a ”calling client”.2Chapter 13 discusses the difference between executable code which runs on theemulator and on target hardware.
In effect, on Windows, Symbian OS runs in a singleprocess 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 Windowsbuilds it is built as efile.dll.170THE CLIENT–SERVER FRAMEWORK IN THEORYThe client-side server implementation may also be responsible forstarting the server if it is not critical to the system (whereupon it will bestarted when the operating system itself starts).11.3How Do the Client and Server Communicate?A client and a server run in different threads and often in differentprocesses.
When running in different processes, they cannot access eachother’s virtual address spaces, so they use a message-passing protocolto communicate. The communication channel is known as a session. Asession is created by the kernel, which also acts as an intermediary forall client–server communication. A client may have several sessions witha server, although, as I’ll explain later, the number of sessions shouldbe kept to a minimum, because each session consumes resources in thekernel and server.Client–server communication occurs when the client makes a requestto the server using a message that identifies the nature of the requestand can additionally hold some parameter data.
For simple transactionsthis is sufficient, but for more complex parameters the server can transferadditional data to or from the client thread using inter-thread data transferfunctions, which I described in Chapter 10.In the rest of this chapter, unless I state otherwise, this discussionassumes that the client and server are running in separate processes,which means that data transfer between them requires inter-processcommunication (IPC). Under these circumstances parameter data cannever be transferred using simple C++ pointers, because the server neverhas direct access to the client’s address space (or vice versa). Instead, thekernel performs the data access on the server’s behalf.When the request has been fulfilled, the server notifies the client thatit has completed by signaling the client thread’s request semaphore,returning a completion result as a 32-bit value.11.4What Classes Does the Client–ServerFramework Use?This section gives an overview of the classes Symbian OS uses toimplement the client–server framework.
For further details of any ofthe classes, you should consult your preferred SDK. The next chapterreviews a typical implementation of a transient server3 and its client-sideaccess code, and further illustrates how the classes I discuss here are used.3A transient server is started by the first client session that connects to it and shuts itselfdown when the last client session disconnects itself. I’ll discuss server startup and shutdownin more detail in Section 11.6.WHAT CLASSES DOES THE CLIENT–SERVER FRAMEWORK USE?171This section provides general background information on how theclient–server framework is implemented. Although it helps to understandwhat is happening ”under the hood”, this information is not necessarysimply to use a Symbian OS server. Most of the rest of the chapter discussesthe implementation of a typical server or the client-side wrapper codethat communicates with a server. If you don’t want to get into this muchdetail, but want to know how to use a Symbian OS server most effectively,you may wish to skip ahead to Section 11.14.The classes I’ll discuss are as follows:• RSessionBase – the client-side base class, representing a sessionwith a server• RMessage – a server-side representation of a client request and itsrequest payload data• DSession – a kernel class that represents a client–server session• CSharableSession – an abstract base class for a server-side representation of a session• CServer – an abstract base class, deriving from CActive, which isused server-side to receive client requests from the kernel and directthem to the appropriate session.RSessionBaseRSessionBase is the main client-side class.
It derives from RHandleBase, which is the base class for classes that own handles to otherobjects, often those created within the kernel. RSessionBase uniquelyidentifies a client–server session.Here’s the declaration of RSessionBase from e32std.h (I’ve omitted a couple of private methods):class RSessionBase : public RHandleBase{public:enum TAttachMode {EExplicitAttach,EAutoAttach};public:IMPORT_C TInt Share(TAttachMode aAttachMode=EExplicitAttach);IMPORT_C TInt Attach() const;protected:inline TInt CreateSession(const TDesC& aServer,const TVersion& aVersion);IMPORT_C TInt CreateSession(const TDesC& aServer,const TVersion& aVersion,TInt aAsyncMessageSlots);IMPORT_C TInt Send(TInt aFunction,TAny* aPtr) const;IMPORT_C void SendReceive(TInt aFunction,TAny* aPtr,TRequestStatus& aStatus) const;IMPORT_C TInt SendReceive(TInt aFunction,TAny* aPtr) const;};172THE CLIENT–SERVER FRAMEWORK IN THEORYThe methods of this class are used to send messages to the server.
You’llnotice that most of them are protected. This is because the client-side classwhich accesses a server will typically derive from RSessionBase (forexample, class RFs, which provides access to the file server). The derivedclass exports functions that wrap RSessionBase communication withthe server and are more meaningful to potential clients of the server (suchas RFs::Delete() or RFs::GetDir()).The overloads of RSessionBase::CreateSession() start a newclient–server session. They are typically called by client-side implementation code in an exported method such as Open() or Connect().As an example, when you start a session with the file server youcall RFs::Connect(), which itself calls RSessionBase::CreateSession().
When the session is opened successfully, correspondingkernel and server-side objects are created.A server has a unique name which must be passed to RSessionBase::CreateSession() to connect the client to the correct server.Again, the client-side implementation takes care of this, so the callingclient does not need to know the name of the server.
CreateSession()also takes a TVersion structure4 for compatibility support.You’ll notice that one overload of CreateSession() takes an integer parameter called aAsyncMessageSlots. This value reserves anumber of slots to hold any outstanding asynchronous requests thatclient session may have with the server.5 The maximum number of slotsthat may be reserved for each server is 255. The other overload ofCreateSession() does not pre-allocate a maximum number of message slots. Instead, they are taken from a kernel-managed pool, of upto 255 message slots for that server, which is available to the wholesystem. If the number of outstanding requests to a server exceeds thenumber of slots in the system pool, or the number reserved for a particular session, the asynchronous request fails to be submitted and completesimmediately with the error KErrServerBusy.A request to a server is issued through a call to RSessionBase::SendReceive() or RSessionBase::Send().