amiga-sources@sugar.uu.net (alt.sources.amiga) (09/11/88)
Archive: uunet!~uucp/amiga-sources/ipc.docs.Z : #! /bin/sh # This is a shell archive, created on Sugar Land Unix (..!uunet!sugar) # by amiga-sources (alt.sources.amiga) on Sun Sep 11 08:14:11 1988 # Remove anything before the "#! /bin/sh" line, then unpack it by saving # it into a file and typing "sh file". If you do not have sh, you need # unshar, a dearchiving program which is widely available. In the absolute # wost case, you can crack the files out by hand. # If the archive is complete, you will see the message "End of archive." # at the end. # This archive contains the following files... # 'READ_ME' # 'ipc.doc' # To extract them, run the following through /bin/sh echo x - READ_ME sed 's/^X//' > READ_ME << '//END_OF_FILE' X X Inter-Process Communication Standard X ==================================== X X July/Aug 1988 X X XThe stuff in this release is a result of several months' work by several Xpeople on usenet. The goal has been to develop a standard for Inter-Process XCommunication on the Amiga (henceforth known as "IPC"). This standard is Xcompletely Public Domain, and we think it could lead to some outstanding Xnew capabilities for this machine. The basic standard is now in a fairly Xstable -- hence publishable -- form. So, here it is. X X X What's in this release X ====================== X XThis release (through alt.sources.amiga) contains only sources and Xdocumentation. There should be four shar format files in the package, Xas follows (see below for details): X X IPC_docs.shar -- this READ_ME and ipc.doc X IPC_src.shar -- IPC include headers and system source files X IPC_demo_src.shar -- Some simple demo code X IPC_manx_demos.shar -- Some demo code written directly in Manx/Aztec C X X XThe complete release (available by anonymous FTP from ucbvax) currently Xcontains the documentation (plain text) file, the sources in shar format, Xand one zoo-format compressed binary file containing the demo (demo_src) Xin executable form. [DON'T FORGET to use BINARY mode when ftp'ing this!]. X X XIPC_docs.shar -- contains this READ_ME, plus: X X ipc.doc -- A description of the IPC concept and this standard. X (Not yet as complete as I know it ought to be...) X XIPC_src.shar X -- An archive containing the source files for the IPC X system routines. See the READ_ME file in the archive X for contents and details. X XIPC_demo_src.shar X -- An archive containing source files for the demo X program modules "Pserver" and "MinClient". See the X READ_ME file in the archive. X XIPC_manx_demo.shar X -- A client/server pair written by Brian J. Witt in X Manx/Aztec C to demonstrate and test the IPC system. X (They will also compile under Lattice.) X X X %%%%%%%%%%%%% X X XAcknowledgments and attributions: X XThis package and its contents were compiled by Pete Goodeve, who should be Xflamed... er.. blamed... for all its inadequacies. All the code here except Xfor the Manx demos was also written by Pete. X XThe IPCMessage format was largely the design of Peter da Silva. X XThe mechanism used to manage IPCPorts safely ("use counts") was originally Xsuggested by Matt Dillon. X XThe additions to IPC.h and IPC.c needed to make it compatible with Manx C Xwere supplied by Brian Witt, who also wrote the Manx format demos. X XEssential criticism and suggestions have come from Stuart Ferguson, Ron XMinnich, Chuck McManis, Leo Schwab, and many other denizens of the net. XI know I've omitted some names I shouldn't have, but a lot of messages (of Xthe net variety) have been flowing during the past many months. XMuch appreciation is due to all who have taken the trouble to read, Xconsider, and contribute to the mass of material that has accumulated. XThank you all! X X 1988 September 1 X X Pete Goodeve X 3012 Deakin Street #D X Berkeley, Calif. 94705 X X [...ucbvax!violet!pete] X X X %%%%%%%%%%%%% X //END_OF_FILE echo x - ipc.doc sed 's/^X//' > ipc.doc << '//END_OF_FILE' X X An Inter-Process Communication Standard for the Amiga X ===================================================== X XThis is initial documentation for the IPC standard developed via usenet Xover the past several months. A large part of the standard is now fairly Xstable (the IPCPort mechanism in particular), but there is a lot of work Xstill to be done on the details, on developing message IDs for specific Xfunctions, and on publishing them. Anyway, in its present state, here it Xis. X X XWhy IPC? X======== X XUp to now, even though the Amiga is the first really totally multitasking Xpersonal computer, programs for it have been written much as for any of the Xolder one-job-at-a-time machines (though they often take good advantage of Xthe windowing environment): they run as single processes. A few programs Xspawn child tasks to perform some of their functions, but they are still Xmonolithic in their design. X XThere is an alternative. A ... let's call it a "Job environment"... could Xbe serviced by a number of more specialized processes, communicating with Xeach other. Depending on the needs of that environment, these processes Xcould be very specialized -- a note bender in a MIDI system, say -- or more Xgeneral, like a text editor that called up things like a spell checker or Xoutput formatter when needed. Such a system would give the user much more Xchoice in configuring it to his/her preferences. (Not forgetting though Xthat a default configuration would have to be as easy to use as any well Xdesigned program!) The modules in an environment wouldn't all have to come Xfrom one company, as the interface to invoke a module's function would be Xpublished with the module. You could add special purpose functions to a Xpaint program say, just by starting up another process that would Xrecognize, or be recognized by, the paint program. X XThere are a lot of possible applications of this principle, with widely Xvarying requirements. Here is a very incomplete list of a few that come to Xmind: X X * Communications -- connect terminal emulators, protocol handlers X [Kermit, XModem etc.], auto-answer modules, script X processors etc. to suit the user's environment. X [Note the wide range of parameters such as processing X speed demanded by different modules: protocol handlers X will have to operate character by character at baud X rates, while script servers and auto-answer can be much X more leisurely.] X X * MIDI Modules -- a lot of possibilities here for a fast IPC X protocol; anything you might want to do to a MIDI X channel could be a "plug-in" module. X X * Data Acquisition and Control -- there are untapped opportunities X for a multitasking machine in the laboratory; being X able to "plug" modules together like you can with lab X equipment would be a great attraction. X X * Desktop Publishing -- put together a comprehensive and competent X system from the pieces YOU prefer. X X * Desktop Video and Presentation -- lots of enticing possibilities X here; the real-time nature of presentation gives lots X of opportunities for fast IPC. (One might even think X of coupling several machines together...!) X X * Service Programs -- to do common jobs for other modules; small ones X -- print format servers, pattern matchers, directory X searchers etc. -- can take a lot of the load off other X modules that would otherwise have to include code for X those things; larger ones could handle jobs like spell- X checking for any program that wanted it. X X * A Multitasking H*perC*rd -- a somewhat vaguely specified, but X highly enticing, goal; dream your own scenario... X X XThis should give some flavor of the ways in which I think a general X"Cooperating Processes Paradigm" would be a winner. You can see that a Xwide range of schemes could fall under the term "IPC". It would be nice if Xthey could all be handled by one underlying protocol. X XThere are a number of possible candidates. Processes can pass information Xbetween each other via files and pipes, for example. This has the great Xadvantage that it is already built into the system, but its disadvantage is Xthe heavy overhead involved in file-type I/O. Also, simple serial stream, Xunstructured, communication isn't good enough for a system that is going to Xpass around many different types of information. The receiver of Xinformation has to know exactly what it is getting, and the sender must Xknow exactly how to tell it. X XThis means some kind of standard structure for the data that can be Xunderstood by all processes. IFF is such a standard, but again Xunfortunately it is too complex and serial-oriented for very fast Xcommunication. Its principles make a good starting point though. X XThere is an obvious candidate built into the Amiga Exec: Messages and XPorts. These are actually just about what we want, but there are a couple Xof problems with them as they stand. X XFirst, although ports work perfectly when child tasks spawned and managed Xby a single master process use them to talk to each other, there is no Xprotection against accidents that are likely to occur when independent Xprocesses communicate. The problem is that, as ports are accessed by a Xpointer, there is no way of being sure that the port pointed to still Xexists when you want it, unless you lock out all other processes before you Xget the pointer, and don't unlock them again until you've used it. This Xcan get VERY cumbersome and inefficient if you want to send a lot of Xmessages to a port, as you have to do the Forbid/Find pointer/Use pointer/ XPermit sequence for every message. X XSecond, there is the problem of a process knowing exactly what is in the Xmessage it has received. As we said, there must be a Standard Structure Xfor the data in the message so that it becomes easy for different authors Xto write programs that can understand each other. X XHence the IPC Standard really breaks down into two parts: IPCPorts and XIPCMessages. These are essentially independent of each other, in that the XPorts have no knowledge or concern about the message structure (aside from Xthe necessity for the standard Exec Message structure at its heart), and Xconversely the Messages are not concerned with the Port procedures. X XIt should be pointed out that this is a "Foundation Level" protocol. It Xdefines how ports should be managed, and the common structure of messages, Xbut says nothing more about how they are to be used. There are many higher Xlevel considerations, such as how the processes should appear to the user, Xand how he is to control them, that need to be worked out. There are a lot Xof possibilities here: control panels, patch panels, "drop-in" menus; some Xapplications will need added capabilities such as command languages and Xscripts; others would be slowed unacceptably by such overhead. But with Xluck this standard will be general enough to cover the range. X XThere are other schemes, actual and potential, that have to be considered Xin relation to this one. In general there is probably no need for them to Xbe competitors. One such is AREXX, which has already been successful in Xapplications like integrating editors with text formatters; because it is Xbasically an interpreted script language, it doesn't seem so suitable for Xsome of the other potential applications mentioned above. There seems no Xreason though why an interface between AREXX and this standard could not be Xwritten; only a restricted set of IPCMessages could be handled, but Xprobably enough to give great flexibility. X XAnother possibility is an "Object Oriented" communication scheme. This has Xboth similarities and differences to this protocol, but is still in rather Xformative stages at this point. We will have to wait to see if the two Xschemes can coexist: I believe they can. X X XIPCPorts X======== X XAn IPCPort is a rendezvous point between processes where messages can be Xdropped off and picked up. It is identical in concept to the standard XAmiga Exec MsgPort (see the Rom Kernel Manual), but is managed so that Xmessages cannot be sent to a non-existent port (if the processes obey the Xrules!). Any number of "Client" processes can be sending messages to a Xport at one time, but there can be only one "Server" on a port. If a port Xdoesn't have a Server -- either running or in the process of being loaded X--, it is "Closed", and won't accept messages. X XUnlike an Exec MsgPort, an IPCPort doesn't "belong" to any particular Xprocess, and a program must never create one directly or assign memory in Xits own space for one: a port will be created by the first process that Xneeds it, and will remain available until all references to it have been Xcleared; it may be finally deleted by the last user long after the first Xhas gone away. Either a Server or Client may make the first reference. X XEach port is identified by a unique name (although unnamed anonymous ports Xare also possible, as we'll see later); the name may be any appropriate Xnull-terminated byte string. A port is located by an exact match to the Xstring: the case of the characters is respected. The author of a server Xwill publish the names of the ports it services, so that others can write Xclients to access it; if two programs offer alternatives for the same Xservice, they should use the same port name, so that the user may plug one Xof them in without changing the client. X XIPCPorts are managed by a procedure module linked in with each program that Xuses IPC. No separate manager process is needed, although for more Xflexibility it is possible to run a "Port Broker" that manages the loading Xof servers when their ports are requested (this will probably become the Xusual mode). At the moment, each program must have its own copy of the Xcode, but it will eventually be a resident library. X X XClients and IPCPorts X==================== X XWhen a Client process first needs a port of a particular name, it must get Xa pointer to that port. The pointer will then remain valid until the XClient specifically drops its access request. Each request made MUST be Xpaired eventually with a drop for correct port management. X XThere are three possible ways of getting a port pointer. Each of these Xprocedures takes a names string as argument and returns the pointer if Xpossible. They differ in the actions they take to ensure the status of the Xport. X X GetIPCPort(name) always returns a valid pointer (unless memory is X full, or some other disaster strikes). The port is X created if it doesn't exist. No indication is X given as to whether there is a current server. X X FindIPCPort(name) only returns a pointer if the port already exists X and has a server; otherwise it returns NULL. X X LoadIPCPort(name) (an addition to the basic procedures that is in its X own module) does a GetIPCPort, but if the port has X no server it calls on a "Port Broker" process X (also an addition to the basic system) to load one; X if the broker can't do this (or the broker doesn't X exist) the port will be dropped again, and NULL X will be returned. If a valid pointer is returned, X you can assume that a server exists or is being X loaded. X X LoadIPCPort does not wait for the server to be X loaded, but the "Loading" flag will be set in the X port so that it will accept messages for the server X to handle when it arrives. X XEach successful call to one of these procedures increments the "Use Count" Xof the port. To reduce the use count again you must end the Client's Xaccess to the port by: X X DropIPCPort(port) where 'port' is the pointer returned by any of the X above calls. The use count is reduced by one: if X it goes to zero, the port is deleted. X XA Client must not exit without dropping all the ports it has acquired (and Xof course must not drop them more times than it has acquired them!). X X XA Client sends messages to an IPCPort by a call exactly analogous to Exec's XPutMsg(), but the Exec call has no way of detecting the presence or absence Xof a Server, so it cannot be used. Instead use: X X PutIPCMsg(port,message) where 'port' is a valid pointer, and 'message' X is a pointer to an IPCMessage. It returns TRUE X if the message was successfully queued on the X port; if the port has no server either present X or loading, it will not send the message and X will return FALSE. X XUnless there are specific reasons otherwise, a message sent to a Server Xwill eventually be replied, and the Client must handle this also by Xsupplying a Reply Port. The reply path does not need the IPCPort protocol, Xbecause a Client MUST keep the reply port available until it has received Xback ALL the replies it is expecting, so normally this can be a standard XExec MsgPort. There is no reason though why it should not be an IPCPort as Xwell if you prefer -- even one used for other communications -- as long as Xyou bear in mind that replies will be sent to it whether or not it has a Xserver assigned. X X XServers and IPCPorts X==================== X XThe Server uses a complementary set of procedures to a Client to manage a Xport. There is only one way it can acquire a port: X X ServeIPCPort(name) makes this process the server for the named port X if possible and returns a valid pointer to the X port. The port is created if it doesn't exist. If X a server already exists for the port, the call will X return NULL. (If successful, it also increments the X use count.) X XTerminating service on the other hand is normally a two-step process. XFirst the server must shut the port against further incoming messages, then Xhandle and reply to any messages still queued on the port, and finally free Xup the port for eventual reclamation or for another server to claim it. X X ShutIPCPort(port) just marks the port as "Shut". The server remains X attached to the port and can receive signals from X it (for example if the number of clients changes, X see below), but PutIPCMsg calls will be blocked. X X LeaveIPCPort(port) removes this process from association with the X port. Also does a DropIPCPort to decrement the use X count and delete if appropriate. X XBetween the ServeIPCPort and the ShutIPCPort, the server must be prepared Xto accept messages on that port. In most cases it will probably spend the Xmajor portion of its time waiting on that port -- or possibly several ports X-- for a message to arrive. All this area of the server's operation is Xhandled by standard Exec calls: WaitPort() or Wait(), GetMsg(), and XReplyMsg() (see the Rom Kernel Manual). X XIf it only has one port to wait on, it can use: X X WaitPort(port) which suspends the process until a message arrives at X that port. X XThis is liable to be inadequate though, because it will only be woken up by Xmessages arriving on that particular port. It is NOT awakened by other Xsignals to the process, even if they use the same signal bit (see the RKM Xfor Task Signals). Thus you are more likely to want to use: X X Wait(sigbits) where 'sigbits' is a 32-bit mask of all the signals you X want to be awakened on. It returns the signals that X were actually set, so the process can determine if it X needs to take unusual action. X XThis means, though, that you have to create the sigbits mask from the Xsignal bit number contained in the port itself (and other bits that you Xwant to respond to). There is no specific call to get this (though there Xshould probably be at least a macro), but if the server is just using IPC.h Xas a header (and not IPCPorts.h) IPCPorts are equated to MsgPorts, so you Xcan get the bit by: X X sigbit = 1L<<port->mp_SigBit; X XNote that this bit is also used by the "Notify" feature (below) to awaken Xthe server if the number of clients changes. No message is associated with Xthis signal, but all the server has to do is check the number of clients X(again, below) each time it is awakened. X XTo process a received message, the server simply uses GetMsg(), though it Xis preferable to cast the returned value to the correct type: X X msg = (struct IPCMessage *)Getmsg(port); X XWhen done with the message, it should use ReplyMsg() in the normal way X(using a cast if your compiler applies prototype checks): X X ReplyMsg((struct Message *)msg); X X XChecking IPCPort Status X======================= X XEither Client or Server can get information about the current state of an XIPCPort with the CheckIPCPort() call. The Server alone can also set Xthe state of certain flags in the port (only one is currently defined). X X CheckIPCPort(port,flags) as long as the high bit of 'flags' X (a 16-bit value!) is not set, returns the X number of users (including the server) X currently aware of the port; if the high X bit is set (0x8000 -- this should be a X defined identifier... an omission in the X current IPC.h, sorry), the call instead X returns the current flags set in the port. X When called by the current Server ONLY, the X value in the low 8-bits of the 'flags' X argument will be set into the port's Flags X slot; system flags in the upper 8-bits of X the slot are not affected. X XAlthough a Client may use this call, it will probably have no need to, Xunless it wants to check for the presence of a Server without making a XPutIPCMsg call. The Server, however, can use the call to keep tabs on how Xmany clients actually require its services, and optionally terminate if Xthere are none. To do this it will want to be notified if the number of Xclients changes; this can be done by setting the IPP_NOTIFY flag in the Xport: while that is set, any call that acquires or drops a port will send a Xsignal to the Server process (using the signal bit defined for that message Xport); no message is actually sent, but the Server should call CheckIPCPort Xeach time it is woken up. X X XAnonymous IPCPorts X================== X XIt is possible to create IPCPorts that are unnamed, but these obviously Xcannot be acquired independently by other processes without a name to Xaccess them by. The associated pointers must be passed to other processes Xvia some standard message pathway (left up to the processes concerned). XThey still should obey the IPC rules, though, so another procedure is Xprovided for acquiring them: X X UseIPCPort(port) registers another user for that port (i.e. X increments the use count). X XWhen the user process is done, it issues DropIPCPort in the usual way. X XYou create an anonymous IPCPort by: X X ServeIPCPort(NULL) which will return a pointer to a NEW port for X each call, and set the caller as the Server. X (It will only fail if there is no memory or some X such fatal problem.) X XFor special cases -- e.g. ReplyPorts -- where you know PutIPCMsg will never Xbe used, you could instead use GetIPCPort(NULL), but there is NO way of Xregistering a server on an anonymous port except at creation time. X X +++++++++++ X XIPCMessages X=========== X XThe format of IPCMessages is intended to be very flexible, yet specific Xenough that a Server can immediately determine the function and content of Xa message it receives (or reject it if it does not recognize it). X XThe protocol has two levels where identification is specified. There is a Xfixed structure Message header (basically an Exec Message structure with Xadded information) which includes a Message ID, followed by an arbitrary Xnumber of "Items", each again of fixed structure with its own Item ID. XEach item in turn usually points to a block of memory where the actual data Xfor the item is stored. Instead of a pointer, a single 32-bit value can be Xstored in the item itself. In special cases, the data pointed to may be Xmore complex than a single data block (a list, say) but then the Xrestrictions on what can be done with the message increase markedly. XAs long as all the items in a message are simple data blocks (or single Xwords), it can be passed between servers that do not have to understand the Xcontents of those blocks: deletion of the message, for example can be done Xby any server. Flags in the message and each item indicate whether the Xdata is private to the originating process or can be transferred to the Xreceiver, whether it is suitable to send out on a network, and so on. X XAn ID -- Message or Item -- is a 32-bit longword, normally a four-character XASCII code. All "Published" IDs should be of this form, but cooperating Xprocesses could perhaps use non-ASCII numeric values internally. If the Xfirst (high) byte is zero, the ID is a private one. Codes of less than Xfour characters may of course be used, but they preferably should be padded Xon the right with blanks (rather than nulls). Case is important naturally; Xby convention (and analogy to IFF) upper case is preferred, but there is no Xfirm requirement for this; lower case should probably be used to extend on Xmeanings that were orignially upper case. X XFor details on IPCMessage structure, and the various flags currently Xdefined, please refer to the IPC.h header file. [A fuller discussion will Xbe included in a future revision of this document...] For examples of IDs, Xlook at the demo example sources on this disk. [Again, at some point not to Xfar distant, I hope to publish a list of IDs suggested for various Xfunctions.] When assigning your own IDs, please do it with future Xexpansion in mind, and publish them on usenet or elsewhere as soon as Xpossible for comment. X X XMessage Structure X================= X X(briefly) X XEach message has a header which is a standard message structure, followed Xby an ID field (32-bits), a 32-bit Flags field, and an Item Count X(16-bits). This is immediately followed by that number of items, each of Xwhich has the following structure: Item ID (32-bits), Flags (32-bits), XSize of data block (32-bits), and Pointer to data block. This may in turn Xbe followed by a data area containing the data for some or all of the items Xin a message; this may or may not be convenient, depending on the nature of Xthe data. The mn_Length field in the standard message structure indicates Xthe complete length of the message (remember it is only 16-bits, so the Xmaximum size of a message containing in-line data is 64K). X XAs already remarked, the "Pointer" field of an item may not in fact point Xto a single block of data, but may be a single value or a NON-STANDARD Xpointer (a BPTR for example). In both these cases, the Size of the item Xshould be set to ZERO. The Flags field will give other information about Xthe item, some system, some private (defined by the application). For the Xcurrent system flags, please see IPC.h. X X XManaging IPCMessages X==================== X XTwo system procedures are provided for convenient management of memory for XIPCMessages (much preferable to the program doing it all for itself). X X CreateIPCMsg(items, extra, replyport) creates a new message block X for that number of 'items' X (0..n), with 'extra' bytes of memory after the X items for data storage (you will have to get X its offset as the location of the "item" X following the last actual item); the X 'replyport' pointer is inserted in the standard X message structure. It returns a pointer to the X created message (or NULL if there is no space). X X DeleteIPCMsg(msg) deletes the memory block created by X CreateIPCMsg. It does NOT attempt to handle X memory occupied by data outside the message and X pointed to by its items. X X X[This document is still in progress -- apologies for omissions] X X X +++++++++++ X X Pete Goodeve X July 1988 X //END_OF_FILE echo "End of archive." # end of archive. exit 0