• Keine Ergebnisse gefunden

Defining Parameters for a Procedure

Im Dokument Standards Programming (Seite 175-184)

Word i=O;

/* get the maximum size of the message */

if(cbDataRet

<

cbMsgRet) i cbDataRet;

else

i = cbMsgRet;

/* put the message in the user's buffer */

memcpy(pbDataRet, rgMsgRet, i);

*«Word *) psDataRet) = i;

/* return ercOK */

return(O);

}

pragma Calling_convention();

Listing 9-1. Sample System-Common Procedure

Defining Parameters for a Procedure

When a system-common service installs one of its system-common procedures, it passes two things to the operating system: the system-common procedure number, and a character string that defines the parameters for that procedure.

This section explains the format of the parameter-definition string.

System-common procedure numbers are discussed later in this chapter, under "Defining System-Common Procedure Numbers."

System-common services should supply a parameter-definition string for each system-common procedure they install. If a procedure takes no parameters, the parameter-definition string should be a null pointer with a zero length.

The syntax for defining system-common procedure parameter lists is shown in the following paragraphs. This syntax is in Backus-Naur Form (BNF) language.

9-6 eTOS/ Open Programming Practices and Standards - Part I

<definition string> ::= <definition string> <term>

<term> ::= <word term>

I

<selector term>

I

<pointer term>

I

<pointer term> <count term>

<word term> ::= w

<selector term> ::= s

<pointer term> ::= <input pointer term>

I

<returned pointer term>

<input pointer term> ::= p

<returned pointer term> ::= q

<count term> ::= c For example, for the call

GetFooText(Pointer pbDataRet, Word cbDataRet, Pointer psDataRet)

the string defining the parameter list would be "pcp" where the calling sequence is "pointer, count, pointer." The operating system can then use this string to create alias pointers, if it needs to. For example, when the operating system intercepts ( traps) a call made by a real mode program to the installed procedure, the operating system creates an alias GDT selector for each pointer in the parameter-definition string.

The operating system may modify this string for its own purposes internally, but it will not change the meaning or the order of the parameters. Any changes are purely for the operating system's internal use. A system-common service should not, however, expect to receive the same parameter definition string on a System Common Query that it passed on a previous SystemCommonInstall.

Installation and Deinstallation

System-common services can be installed and deinstalled, much like request-based system services. Usually, a system-common service serves only a single request. That request is issued by the service's deinstallation utility, and is used to deinstall the service.

Writing Systeln-Common Services 9-7

Installation

A system-common service uses almost the same installation procedure as a request-based system service does. The key difference is that instead of serving a request for each of its major functions, a system-common service installs each of its system-common procedures.

The system-common service first calls System Common Query for each procedure to determine whether the desired system-common procedure number has already been declared to the operating system. This step is even more important that the QueryRequestlnfo call in a request-based service. This is because a system-common service performs no process comparable to merging request files for a request-based service.

Therefore, if two system-common services use the same system-common procedure number, that fact may not be detected until run time.

As with a request-based system service, a system-common service should save the existing state of its system-common procedure numbers, then restore them when it deinstalls.

A typical installation sequence is:

1. Call GetPartitionHandle to see if the service is already installed in another partition. A system service should not install if it is already present on the current processor.

2. Allocate any resources to be used by the system-common service.

This includes allocating exchanges, allocating memory, and creating any additional processes.

3. Query the current status of the deinstallation request the service will serve. This lets the service make sure the request is declared in the operating system. If the request is undeclared, the service should abort. The service should also save the values returned by the query so that it can restore them when it is deinstalled.

4. Query the current status of the system-common procedure numbers the service will use. This lets the service make sure they are not already in use. The service should save the values returned by the queries so that it can restore them when it is deinstalled.

5. Perform ConvertToSys, then Exit. The ConvertToSys operation changes all processes, exchanges and memory in the partition from 9-8 eTaS/Open Programming Practices and Standards - Part I

application status to system service status. This converts the partition to a system service partition. The Exit operation then reloads the exit run file into memory.

6. Change priority, so that the service runs at a higher priority than any potential client application.

7. Use the SetPartitionName operation to identify the service to the operating system.

8. Perform a ServeRq operation for the deinstallation request.

9. Perform a SystemCommonlnstall operation for each of the service's system-common procedures.

As with a request-based system service, the order of the operations before ConvertToSys can be changed, and the order of the operations after ConvertToSys can be changed. Compatible programs generally should not, however, move an operation from before to after ConvertToSys, or from after to before.

Listing 9-2 shows an example of how a system-common service might install itself. The service installs its system-common procedures, then waits at its exchange for a deinstallation request.

void main(){

RqHeaderType *pRqi

CheckErc(GetUserNumber(&usernum»i CheckErc(AllocExch(&exchServe»i

/* This is the already-installed test. If already */

/* present, set up an exit message, and exit */

if (GetPartitionHandle(rgServerName, srgServerName,

&PhRet) == ercOK) [

ErrorExitString(O, rgInstMsgl, srgInstMsgl)i

/* query the system-common procedure. If i t is in */

/* use, error exit. */

CheckErc( SystemCommonQuery(IDSYSCOM, &rgSysComInfo, sSysComInfo»i

if(rgSysComInfo.fDefined != FALSE)

ErrorExitString(O, rgRqInUse, srgRqInUse)i

continued ...

Writing System-Common Services 9- 9

/* query the request. If i t is in use, error exit. */

Listing 9-2. System-Common Service Installation 9-10 eTaS/Open Programming Practices and Standards - Part I

Deinstallation

The procedure to deinstall a system-common service is similar to the one for a request-based service.

A system-common service generally serves only a deinstallation request, so it need not concern itself with outstanding requests. However, there is a deinstallation issue raised by the nature of system-common procedures:

a client may be currently executing the procedure when it is deinstalled.

If this happens, the client's selector is suddenly invalid. The next instruction the client program executes will cause a protection fault, and the client program will fail. For this reason, a system-common service should only be deinstalled if none of its clients are active.

When a system-common service receives a deinstallation request, it should:

1. Restore the request table in the operating system to its original state for the service's deinstallation request, by issuing a ServeRq opera-tion with the saved value from installaopera-tion time.

2. Restore the system-common procedure table by calling SystemCommonlnstall with each saved value from installation time.

3. Close any connections the service may have opened as a client (with the file system, for example).

4. Unlock its own partition by calling SetPartitionLock, then respond to the deinstallation request.

5. Terminate by calling ExitAndRemove.

Listing 9-3 shows the deinstallation procedure for a system-common service.

Writing System-Common Services 9-11

void DeInstall(RqHeaderType *pRq) /* unserve the requests */

CrashlfErcNotOk(ServeRq(DEINSTRQ, rqlnfo.exch»i CrashlfErcNotOk(SystemCommonlnstall(IDSYSCOM,

rgSysComlnfo.pProc, rgSysComlnfo.rgbPararnDef, rgSysComlnfo.srgbParamDef, 1, NULL, 0) )i

/* All done, unlock partition, and deinstall */

CrashlfErcNotOk (SetPartitionLock(FALSE»i /* unlock partition */

Respond(pRq)i /* respond to deinst. rq */

ExitAndRemove()i /* bye */

Crash(3); /* Bad problem if we ever get here */

Listing 9-3. System-Common Service Deinstallation Procedure

Defining System-Common Procedure Numbers

Like requests, system-common procedures each have a code number that identifies them to the operating system. For applications to use them, each system-common procedure also needs to have a symbolic natne.

What You Need to Define

For a client program to call a system-common procedure, it must know the symbolic name for that procedure. To define symbolic names for your system-common procedures, you must create a system-common label object file, then link that file with the client application. This way, the client application can simply call the system-common procedure by name, as an external procedure. For example:

GetFooText(&rgbServerData, cbServerData, &sDataRet)i System-common procedures can use procedure numbers 6000h through 7FFFh without restriction. You can also reserve system-common procedure numbers in the range from 4000h to 5FFFh by contacting Unisys Network Computing Group, CTOS/BTOS Technical Support.

9-12 eTOS/ Open Programming Practices and Standards - Part I

Making a System-Common Label Object File

Most implementations of eTaS/Open provide an Assembler macro,

% OsSubLab , which aids in defining system-common procedure labels.

This macro is generally located in the file OsSub.mdf. See your operating system documentation for more information. Listing 9-4 shows an example of a system-common procedure definition file for a system-common service.

STACK SEGMENT STACK 'STACK' DB 512 DUP (?)

STACK ENDS

$include([Sys]<Sys>ossub.mdf)

%OsSubLab(26005, "GetFooText")

default stack

Listing 9-4. Sample System-Common Label File

Writing System-Common Services 9-13

Im Dokument Standards Programming (Seite 175-184)