home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 164.lha / IPC / ipc.doc < prev    next >
Text File  |  1988-04-28  |  25KB  |  487 lines

  1.  
  2.           An Inter-Process Communication Standard for the Amiga
  3.           =====================================================
  4.  
  5. This is initial documentation for the IPC standard developed via usenet
  6. over the past several months.  A large part of the standard is now fairly
  7. stable (the IPCPort mechanism in particular), but there is a lot of work
  8. still to be done on the details, on developing message IDs for specific
  9. functions, and on publishing them.  Anyway, in its present state, here it
  10. is.
  11.  
  12.  
  13. Why IPC?
  14. ========
  15.  
  16. Up to now, even though the Amiga is the first really totally multitasking
  17. personal computer, programs for it have been written much as for any of the
  18. older one-job-at-a-time machines (though they often take good advantage of
  19. the windowing environment): they run as single processes.  A few programs
  20. spawn child tasks to perform some of their functions, but they are still
  21. monolithic in their design.
  22.  
  23. There is an alternative.  A ... let's call it a "Job environment"... could
  24. be serviced by a number of more specialized processes, communicating with
  25. each other.  Depending on the needs of that environment, these processes
  26. could be very specialized -- a note bender in a MIDI system, say -- or more
  27. general, like a text editor that called up things like a spell checker or
  28. output formatter when needed.  Such a system would give the user much more
  29. choice in configuring it to his/her preferences. (Not forgetting though
  30. that a default configuration would have to be as easy to use as any well
  31. designed program!)  The modules in an environment wouldn't all have to come
  32. from one company, as the interface to invoke a module's function would be
  33. published with the module.  You could add special purpose functions to a
  34. paint program say, just by starting up another process that would
  35. recognize, or be recognized by, the paint program.
  36.  
  37. There are a lot of possible applications of this principle, with widely
  38. varying requirements.  Here is a very incomplete list of a few that come to
  39. mind:
  40.  
  41.     *   Communications -- connect terminal emulators, protocol handlers
  42.                     [Kermit, XModem etc.], auto-answer modules, script
  43.                     processors etc. to suit the user's environment.
  44.                     [Note the wide range of parameters such as processing
  45.                     speed demanded by different modules: protocol handlers
  46.                     will have to operate character by character at baud
  47.                     rates, while script servers and auto-answer can be much
  48.                     more leisurely.]
  49.  
  50.     *   MIDI Modules -- a lot of possibilities here for a fast IPC
  51.                     protocol; anything you might want to do to a MIDI
  52.                     channel could be a "plug-in" module.
  53.  
  54.     *   Data Acquisition and Control -- there are untapped opportunities
  55.                     for a multitasking machine in the laboratory; being
  56.                     able to "plug" modules together like you can with lab
  57.                     equipment would be a great attraction.
  58.  
  59.     *   Desktop Publishing -- put together a comprehensive and competent
  60.                     system from the pieces YOU prefer.
  61.  
  62.     *   Desktop Video and Presentation -- lots of enticing possibilities
  63.                     here; the real-time nature of presentation gives lots
  64.                     of opportunities for fast IPC.  (One might even think
  65.                     of coupling several machines together...!)
  66.  
  67.     *   Service Programs -- to do common jobs for other modules; small ones
  68.                     -- print format servers, pattern matchers, directory
  69.                     searchers etc. -- can take a lot of the load off other
  70.                     modules that would otherwise have to include code for
  71.                     those things; larger ones could handle jobs like spell-
  72.                     checking for any program that wanted it.
  73.  
  74.     *   A Multitasking H*perC*rd -- a somewhat vaguely specified, but
  75.                     highly enticing, goal; dream your own scenario...
  76.  
  77.  
  78. This should give some flavor of the ways in which I think a general
  79. "Cooperating Processes Paradigm" would be a winner.  You can see that a
  80. wide range of schemes could fall under the term "IPC".  It would be nice if
  81. they could all be handled by one underlying protocol.
  82.  
  83. There are a number of possible candidates.  Processes can pass information
  84. between each other via files and pipes, for example.  This has the great
  85. advantage that it is already built into the system, but its disadvantage is
  86. the heavy overhead involved in file-type I/O.  Also, simple serial stream,
  87. unstructured, communication isn't good enough for a system that is going to
  88. pass around many different types of information.  The receiver of
  89. information has to know exactly what it is getting, and the sender must
  90. know exactly how to tell it.
  91.  
  92. This means some kind of standard structure for the data that can be
  93. understood by all processes. IFF is such a standard, but again
  94. unfortunately it is too complex and serial-oriented for very fast
  95. communication.  Its principles make a good starting point though.
  96.  
  97. There is an obvious candidate built into the Amiga Exec: Messages and
  98. Ports.  These are actually just about what we want, but there are a couple
  99. of problems with them as they stand.
  100.  
  101. First, although ports work perfectly when child tasks spawned and managed
  102. by a single master process use them to talk to each other, there is no
  103. protection against accidents that are likely to occur when independent
  104. processes communicate.  The problem is that, as ports are accessed by a
  105. pointer, there is no way of being sure that the port pointed to still
  106. exists when you want it, unless you lock out all other processes before you
  107. get the pointer, and don't unlock them again until you've used it.  This
  108. can get VERY cumbersome and inefficient if you want to send a lot of
  109. messages to a port, as you have to do the Forbid/Find pointer/Use pointer/
  110. Permit sequence for every message.
  111.  
  112. Second, there is the problem of a process knowing exactly what is in the
  113. message it has received.  As we said, there must be a Standard Structure
  114. for the data in the message so that it becomes easy for different authors
  115. to write programs that can understand each other.
  116.  
  117. Hence the IPC Standard really breaks down into two parts: IPCPorts and
  118. IPCMessages.  These are essentially independent of each other, in that the
  119. Ports have no knowledge or concern about the message structure (aside from
  120. the necessity for the standard Exec Message structure at its heart), and
  121. conversely the Messages are not concerned with the Port procedures.
  122.  
  123. It should be pointed out that this is a "Foundation Level" protocol.  It
  124. defines how ports should be managed, and the common structure of messages,
  125. but says nothing more about how they are to be used.  There are many higher
  126. level considerations, such as how the processes should appear to the user,
  127. and how he is to control them, that need to be worked out.  There are a lot
  128. of possibilities here: control panels, patch panels, "drop-in" menus; some
  129. applications will need added capabilities such as command languages and
  130. scripts; others would be slowed unacceptably by such overhead.  But with
  131. luck this standard will be general enough to cover the range.
  132.  
  133. There are other schemes, actual and potential, that have to be considered
  134. in relation to this one.  In general there is probably no need for them to
  135. be competitors.  One such is AREXX, which has already been successful in
  136. applications like integrating editors with text formatters; because it is
  137. basically an interpreted script language, it doesn't seem so suitable for
  138. some of the other potential applications mentioned above.  There seems no
  139. reason though why an interface between AREXX and this standard could not be
  140. written; only a restricted set of IPCMessages could be handled, but
  141. probably enough to give great flexibility.
  142.  
  143. Another possibility is an "Object Oriented" communication scheme. This has
  144. both similarities and differences to this protocol, but is still in rather
  145. formative stages at this point.  We will have to wait to see if the two
  146. schemes can coexist: I believe they can.
  147.  
  148.  
  149. IPCPorts
  150. ========
  151.  
  152. An IPCPort is a rendezvous point between processes where messages can be
  153. dropped off and picked up.  It is identical in concept to the standard
  154. Amiga Exec MsgPort (see the Rom Kernel Manual), but is managed so that
  155. messages cannot be sent to a non-existent port (if the processes obey the
  156. rules!).  Any number of "Client" processes can be sending messages to a
  157. port at one time, but there can be only one "Server" on a port.  If a port
  158. doesn't have a Server -- either running or in the process of being loaded
  159. --, it is "Closed", and won't accept messages.
  160.  
  161. Unlike an Exec MsgPort, an IPCPort doesn't "belong" to any particular
  162. process, and a program must never create one directly or assign memory in
  163. its own space for one: a port will be created by the first process that
  164. needs it, and will remain available until all references to it have been
  165. cleared; it may be finally deleted by the last user long after the first
  166. has gone away. Either a Server or Client may make the first reference.
  167.  
  168. Each port is identified by a unique name (although unnamed anonymous ports
  169. are also possible, as we'll see later); the name may be any appropriate
  170. null-terminated byte string.  A port is located by an exact match to the
  171. string: the case of the characters is respected.  The author of a server
  172. will publish the names of the ports it services, so that others can write
  173. clients to access it; if two programs offer alternatives for the same
  174. service, they should use the same port name, so that the user may plug one
  175. of them in without changing the client.
  176.  
  177. IPCPorts are managed by a procedure module linked in with each program that
  178. uses IPC.  No separate manager process is needed, although for more
  179. flexibility it is possible to run a "Port Broker" that manages the loading
  180. of servers when their ports are requested (this will probably become the
  181. usual mode).  At the moment, each program must have its own copy of the
  182. code, but it will eventually be a resident library.
  183.  
  184.  
  185. Clients and IPCPorts
  186. ====================
  187.  
  188. When a Client process first needs a port of a particular name, it must get
  189. a pointer to that port.  The pointer will then remain valid until the
  190. Client specifically drops its access request.  Each request made MUST be
  191. paired eventually with a drop for correct port management.
  192.  
  193. There are three possible ways of getting a port pointer.  Each of these
  194. procedures takes a names string as argument and returns the pointer if
  195. possible.  They differ in the actions they take to ensure the status of the
  196. port.
  197.  
  198.     GetIPCPort(name)    always returns a valid pointer (unless memory is
  199.                         full, or some other disaster strikes).  The port is
  200.                         created if it doesn't exist.  No indication is
  201.                         given as to whether there is a current server.
  202.  
  203.     FindIPCPort(name)   only returns a pointer if the port already exists
  204.                         and has a server; otherwise it returns NULL.
  205.  
  206.     LoadIPCPort(name)   (an addition to the basic procedures that is in its
  207.                         own module) does a GetIPCPort, but if the port has
  208.                         no server it calls on a "Port Broker" process
  209.                         (also an addition to the basic system) to load one;
  210.                         if the broker can't do this (or the broker doesn't
  211.                         exist) the port will be dropped again, and NULL
  212.                         will be returned.  If a valid pointer is returned,
  213.                         you can assume that a server exists or is being
  214.                         loaded.
  215.  
  216.                         LoadIPCPort does not wait for the server to be
  217.                         loaded, but the "Loading" flag will be set in the
  218.                         port so that it will accept messages for the server
  219.                         to handle when it arrives.
  220.  
  221. Each successful call to one of these procedures increments the "Use Count"
  222. of the port.  To reduce the use count again you must end the Client's
  223. access to the port by:
  224.  
  225.     DropIPCPort(port)   where 'port' is the pointer returned by any of the
  226.                         above calls.  The use count is reduced by one: if
  227.                         it goes to zero, the port is deleted.
  228.  
  229. A Client must not exit without dropping all the ports it has acquired (and
  230. of course must not drop them more times than it has acquired them!).
  231.  
  232.  
  233. A Client sends messages to an IPCPort by a call exactly analogous to Exec's
  234. PutMsg(), but the Exec call has no way of detecting the presence or absence
  235. of a Server, so it cannot be used.  Instead use:
  236.  
  237.     PutIPCMsg(port,message) where 'port' is a valid pointer, and 'message'
  238.                             is a pointer to an IPCMessage.  It returns TRUE
  239.                             if the message was successfully queued on the
  240.                             port; if the port has no server either present
  241.                             or loading, it will not send the message and
  242.                             will return FALSE.
  243.  
  244. Unless there are specific reasons otherwise, a message sent to a Server
  245. will eventually be replied, and the Client must handle this also by
  246. supplying a Reply Port.  The reply path does not need the IPCPort protocol,
  247. because a Client MUST keep the reply port available until it has received
  248. back ALL the replies it is expecting, so normally this can be a standard
  249. Exec MsgPort.  There is no reason though why it should not be an IPCPort as
  250. well if you prefer -- even one used for other communications -- as long as
  251. you bear in mind that replies will be sent to it whether or not it has a
  252. server assigned.
  253.  
  254.  
  255. Servers and IPCPorts
  256. ====================
  257.  
  258. The Server uses a complementary set of procedures to a Client to manage a
  259. port.  There is only one way it can acquire a port:
  260.  
  261.     ServeIPCPort(name)  makes this process the server for the named port
  262.                         if possible and returns a valid pointer to the
  263.                         port. The port is created if it doesn't exist.  If
  264.                         a server already exists for the port, the call will
  265.                         return NULL. (If successful, it also increments the
  266.                         use count.)
  267.  
  268. Terminating service on the other hand is normally a two-step process.
  269. First the server must shut the port against further incoming messages, then
  270. handle and reply to any messages still queued on the port, and finally free
  271. up the port for eventual reclamation or for another server to claim it.
  272.  
  273.     ShutIPCPort(port)   just marks the port as "Shut".  The server remains
  274.                         attached to the port and can receive signals from
  275.                         it (for example if the number of clients changes,
  276.                         see below), but PutIPCMsg calls will be blocked.
  277.  
  278.     LeaveIPCPort(port)  removes this process from association with the
  279.                         port.  Also does a DropIPCPort to decrement the use
  280.                         count and delete if appropriate.
  281.  
  282. Between the ServeIPCPort and the ShutIPCPort, the server must be prepared
  283. to accept messages on that port.  In most cases it will probably spend the
  284. major portion of its time waiting on that port -- or possibly several ports
  285. -- for a message to arrive.  All this area of the server's operation is
  286. handled by standard Exec calls: WaitPort() or Wait(), GetMsg(), and
  287. ReplyMsg() (see the Rom Kernel Manual).
  288.  
  289. If it only has one port to wait on, it can use:
  290.  
  291.     WaitPort(port)  which suspends the process until a message arrives at
  292.                     that port.
  293.  
  294. This is liable to be inadequate though, because it will only be woken up by
  295. messages arriving on that particular port.  It is NOT awakened by other
  296. signals to the process, even if they use the same signal bit (see the RKM
  297. for Task Signals).  Thus you are more likely to want to use:
  298.  
  299.     Wait(sigbits)   where 'sigbits' is a 32-bit mask of all the signals you
  300.                     want to be awakened on.  It returns the signals that
  301.                     were actually set, so the process can determine if it
  302.                     needs to take unusual action.
  303.  
  304. This means, though, that you have to create the sigbits mask from the
  305. signal bit number contained in the port itself (and other bits that you
  306. want to respond to).  There is no specific call to get this (though there
  307. should probably be at least a macro), but if the server is just using IPC.h
  308. as a header (and not IPCPorts.h) IPCPorts are equated to MsgPorts, so you
  309. can get the bit by:
  310.  
  311.     sigbit = 1L<<port->mp_SigBit;
  312.  
  313. Note that this bit is also used by the "Notify" feature (below) to awaken
  314. the server if the number of clients changes.  No message is associated with
  315. this signal, but all the server has to do is check the number of clients
  316. (again, below) each time it is awakened.
  317.  
  318. To process a received message, the server simply uses GetMsg(), though it
  319. is preferable to cast the returned value to the correct type:
  320.  
  321.     msg = (struct IPCMessage *)Getmsg(port);
  322.  
  323. When done with the message, it should use ReplyMsg() in the normal way
  324. (using a cast if your compiler applies prototype checks):
  325.  
  326.     ReplyMsg((struct Message *)msg);
  327.  
  328.  
  329. Checking IPCPort Status
  330. =======================
  331.  
  332. Either Client or Server can get information about the current state of an
  333. IPCPort with the CheckIPCPort() call.  The Server alone can also set
  334. the state of certain flags in the port (only one is currently defined).
  335.  
  336.     CheckIPCPort(port,flags)    as long as the high bit of 'flags'
  337.                                 (a 16-bit value!) is not set, returns the
  338.                                 number of users (including the server)
  339.                                 currently aware of the port; if the high
  340.                                 bit is set (0x8000 -- this should be a
  341.                                 defined identifier... an omission in the
  342.                                 current IPC.h, sorry), the call instead
  343.                                 returns the current flags set in the port.
  344.                                 When called by the current Server ONLY, the
  345.                                 value in the low 8-bits of the 'flags'
  346.                                 argument will be set into the port's Flags
  347.                                 slot; system flags in the upper 8-bits of
  348.                                 the slot are not affected.
  349.  
  350. Although a Client may use this call, it will probably have no need to,
  351. unless it wants to check for the presence of a Server without making a
  352. PutIPCMsg call.  The Server, however, can use the call to keep tabs on how
  353. many clients actually require its services, and optionally terminate if
  354. there are none.  To do this it will want to be notified if the number of
  355. clients changes; this can be done by setting the IPP_NOTIFY flag in the
  356. port: while that is set, any call that acquires or drops a port will send a
  357. signal to the Server process (using the signal bit defined for that message
  358. port); no message is actually sent, but the Server should call CheckIPCPort
  359. each time it is woken up.
  360.  
  361.  
  362. Anonymous IPCPorts
  363. ==================
  364.  
  365. It is possible to create IPCPorts that are unnamed, but these obviously
  366. cannot be acquired independently by other processes without a name to
  367. access them by.  The associated pointers must be passed to other processes
  368. via some standard message pathway (left up to the processes concerned).
  369. They still should obey the IPC rules, though, so another procedure is
  370. provided for acquiring them:
  371.  
  372.     UseIPCPort(port)    registers another user for that port (i.e.
  373.                         increments the use count).
  374.  
  375. When the user process is done, it issues DropIPCPort in the usual way.
  376.  
  377. You create an anonymous IPCPort by:
  378.  
  379.     ServeIPCPort(NULL)  which will return a pointer to a NEW port for
  380.                         each call, and set the caller as the Server.
  381.                         (It will only fail if there is no memory or some
  382.                         such fatal problem.)
  383.  
  384. For special cases -- e.g. ReplyPorts -- where you know PutIPCMsg will never
  385. be used, you could instead use GetIPCPort(NULL), but there is NO way of
  386. registering a server on an anonymous port except at creation time.
  387.  
  388.                             +++++++++++
  389.  
  390. IPCMessages
  391. ===========
  392.  
  393. The format of IPCMessages is intended to be very flexible, yet specific
  394. enough that a Server can immediately determine the function and content of
  395. a message it receives (or reject it if it does not recognize it).
  396.  
  397. The protocol has two levels where identification is specified.  There is a
  398. fixed structure Message header (basically an Exec Message structure with
  399. added information) which includes a Message ID, followed by an arbitrary
  400. number of "Items", each again of fixed structure with its own Item ID.
  401. Each item in turn usually points to a block of memory where the actual data
  402. for the item is stored.  Instead of a pointer, a single 32-bit value can be
  403. stored in the item itself.  In special cases, the data pointed to may be
  404. more complex than a single data block (a list, say) but then the
  405. restrictions on what can be done with the message increase markedly.
  406. As long as all the items in a message are simple data blocks (or single
  407. words), it can be passed between servers that do not have to understand the
  408. contents of those blocks: deletion of the message, for example can be done
  409. by any server.  Flags in the message and each item indicate whether the
  410. data is private to the originating process or can be transferred to the
  411. receiver, whether it is suitable to send out on a network, and so on.
  412.  
  413. An ID -- Message or Item -- is a 32-bit longword, normally a four-character
  414. ASCII code.  All "Published" IDs should be of this form, but cooperating
  415. processes could perhaps use non-ASCII numeric values internally.  If the
  416. first (high) byte is zero, the ID is a private one.  Codes of less than
  417. four characters may of course be used, but they preferably should be padded
  418. on the right with blanks (rather than nulls).  Case is important naturally;
  419. by convention (and analogy to IFF) upper case is preferred, but there is no
  420. firm requiI5ent for this; lower case should probably be used to extend on
  421. meanings that were orignially upper case.
  422.  
  423. For details on IPCMessage structure, and the various flags currently
  424. defined, please refer to the IPC.h header file.  [A fuller discussion will
  425. be included in a future revision of this document...]  For examples of IDs,
  426. look at the demo example sources on this disk. [Again, at some point not to
  427. far distant, I hope to publish a list of IDs suggested for various
  428. functions.]  When assigning your own IDs, please do it with future
  429. expansion in mind, and publish them on usenet or elsewhere as soon as
  430. possible for comment.
  431.  
  432.  
  433. Message Structure
  434. =================
  435.  
  436. (briefly)
  437.  
  438. Each message has a header which is a standard message structure, followed
  439. by an ID field (32-bits), a 32-bit Flags field, and an Item Count
  440. (16-bits).  This is immediately followed by that number of items, each of
  441. which has the following structure:  Item ID (32-bits), Flags (32-bits),
  442. Size of data block (32-bits), and Pointer to data block.  This may in turn
  443. be followed by a data area containing the data for some or all of the items
  444. in a message; this may or may not be convenient, depending on the nature of
  445. the data.  The mn_Length field in the standard message structure indicates
  446. the complete length of the message (remember it is only 16-bits, so the
  447. maximum size of a message containing in-line data is 64K).
  448.  
  449. As already remarked, the "Pointer" field of an item may not in fact point
  450. to a single block of data, but may be a single value or a NON-STANDARD
  451. pointer (a BPTR for example). In both these cases, the Size of the item
  452. should be set to ZERO.  The Flags field will give other information about
  453. the item, some system, some private (defined by the application).  For the
  454. current system flags, please see IPC.h.
  455.  
  456.  
  457. Managing IPCMessages
  458. ====================
  459.  
  460. Two system procedures are provided for convenient management of memory for
  461. IPCMessages (much preferable to the program doing it all for itself).
  462.  
  463.     CreateIPCMsg(items, extra, replyport)   creates a new message block
  464.                                             for that number of 'items'
  465.                             (0..n), with 'extra' bytes of memory after the
  466.                             items for data storage (you will have to get
  467.                             its offset as the location of the "item"
  468.                             following the last actual item); the
  469.                             'replyport' pointer is inserted in the standard
  470.                             message structure.  It returns a pointer to the
  471.                             created message (or NULL if there is no space).
  472.  
  473.     DeleteIPCMsg(msg)       deletes the memory block created by
  474.                             CreateIPCMsg.  It does NOT attempt to handle
  475.                             memory occupied by data outside the message and
  476.                             pointed to by its items.
  477.  
  478.  
  479. [This document is still in progress -- apologies for omissions]
  480.  
  481.  
  482.                             +++++++++++
  483.  
  484.                                             Pete Goodeve
  485.                                             July 1988
  486.  
  487.