\input texinfo @c -*-texinfo-*- @c %**start of header @setfilename cmdipc.info @settitle cmdipc @afourpaper @documentencoding UTF-8 @documentlanguage en @finalout @c %**end of header @dircategory Interprocess communication @direntry * cmdipc: (cmdipc). System V and POSIX IPC from the command line @end direntry @copying Copyright @copyright{} 2014 Mattias Andrée @quotation Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled ``GNU Free Documentation License''. @end quotation @end copying @ifnottex @node Top @top cmdipc -- System V and POSIX IPC from the command line @insertcopying @end ifnottex @titlepage @title cmdipc @subtitle System V and POSIX IPC from the command line @author by Mattias Andrée (maandree) @page @c @center `' @vskip 0pt plus 1filll @insertcopying @end titlepage @contents @menu * Overview:: Brief overview of @command{cmdipc}. * Invoking:: Invocation of @command{cmdipc}. * Message Queues:: Using message queue * Semaphores:: Using semaphores * Shared Memory:: Using shared memory * Mutexes:: Using mutual exclusives * Conditions:: Using conditions * Barriers:: Using barriers * Shared Locks:: Using shared locks * Rendezvous:: Using rendezvous * GNU Free Documentation License:: Copying and sharing this manual. @end menu @node Overview @chapter Overview System V and POSIX interprocess communication from the command line. In addition to the primities shared memory, message queue and semaphores, this tool can from these primitives construct mutexes, conditions, barriers, shared locks and rendezvous. @node Invoking @chapter Invoking @command{cmdipc} have support for eight types of interprocess communication units: message queues, semaphores, shared memory, mutexes @footnote{Because of the nature of this program, mutexes are a bit degraded.}, conditions, barrers, shared locks and rendezvous. These are constructed from either the three System V interprocess communication primitives: message queues, semaphores and shared memory, or their POSIX variants. The type of interprocess communication unit to use is selected by the follow options, to use the POSIX variant rather than the System V variant add the option @option{-P} (@option{--posix}). @table @option @item -Q @itemx --mqueue Message queue. @item -S @itemx --semaphore Semaphore. @item -M @itemx --shm Shared memory. @item -X @itemx --mutex Mutually exclusive. (Mutex) @item -C @itemx --condition Condition. @item -B @itemx --barrier Barrier. @item -L @itemx --shared-lock Shared lock. @item -R @itemx --rendezvous Rendezvous. @end table To specify which instance of a unit to use, specify its key (not ID) with the @option{-k} (@option{--key}) option. If you do not have a key, your only option is to create one, but you can still create a unit with a specified key. To create a unit use the option @option{-c} (@option{--create}), this will be successful even if the key is already in use, in which case the unit will simply be opened. To fail if the key is already in use, use the option @option{-x} (@option{--exclusive}). @option{-x} can be used with or without @option{-c}, it is interpretation will does not depend on @option{-c}, @option{-c} is implied by @option{-x}. To remove a key, use the option @option{-r} (@option{--remove}). There are two additional options that are recognised. These cannot be used with any other optios. @table @option @item -h @itemx --help Print a list of all options. @item -f @itemx --ftok PATHNAME ID Print a key derived from an existing file and a project ID. The project ID is a integer between the values 0 and 255, inclusively. The derived key is probable to be non-unique. This is a System V IPC function, and is not available, and are not necessary, for POSIX IPC. @end table The following options are recognised for interprocess communication units. @table @option @item -n @itemx --nonblocking Fail with exit value 2 if the unit is currently occupied and cannot be used without waiting. Not available for shared memory. @item -b @itemx --timeout SECONDS Not available for shared memory. Fail with exit value 2 if the unit is currently occupied and cannot be used without waiting for at most @code{SECONDS} seconds. For a non primitive unit, the time to live is reset when it enters its next state. This could mean that it could timeout anywhere between the specifed time and n times the specifed time when n is the number of steps in the action that can block, which with the current units is at most 3. @item -m @itemx --mode OCTAL Permission bits for the created unit. @end table @node Message Queues @chapter Message Queues Message queues are primitives and play well with other programs. Use of message queues are indicated by the @option{-Q} option. Message queues is a way to send short messages between program. The key for a System V message queue is an integer, and the key for a POSIX message queue is an ASCII string with NUL or slash between 1 character and 254 characters long prefixed with a slash. Recognised options for System V message queues: @table @option @item -s @itemx --size SIZE The size of the queue. This is the total length of all message that can be fit into the queue before it starts blocking. @item -t @itemx --type TYPE When sending, a positive integer of the type associated with the message. When receiving, this allows you to control which types of messages are received. Zero means that any type is accepted, a positive value means that only the indicated type is allowed. If the value is negative, the first message of the lowest type that is at most the absolute value of the specifed value is received. @end table Recognised options for POSIX message queues: @table @option @item -s @itemx --size SIZE The maximum size of messages in the queue. @item -z @itemx --spool SIZE The size of the queue. This is the number of messages that can be fit into the queue before it starts blocking. @item -p @itemx --priority NASTYNESS The priority allows you to order messages in the queue. The highest priority message is received first. By default, messages are sent at the lowest priority, that is zero. @end table To receive a message, add the verb @option{receive}. To send a message, add the verb @option{send} followed by the message to send. @node Semaphores @chapter Semaphores Semaphores are primitives and play well with other programs. Use of semaphores are indicated by the @option{-S} option. Semaphores are primitive concurrency units that be used for many different things. Basically, a semaphore is an atomic counter that is never allowed to go below zero. The key for a System V semaphores is an integer, and the key for a POSIX semaphores is an ASCII string with NUL or slash between 1 character and 254 characters long prefixed with a slash. The following options are recognised for semaphores: @table @option @item -i @itemx --initial VALUE You can select the value a semaphore should have when it is created. By default the value is zero. @item -d @itemx --delta DIFFERENCE When increasing or decreasing the value of the semaphore @option{--delta} can be used to select how much the value should change with. By default this is 1. Semaphores are atomic, you are guaranteed to either change the value exactly as much as specified or not all at. @end table The verbs @option{v} and @option{p} are used to increase or decrease the value of the semaphore, respectively. You can also set the exact value of the semaphore with the @option{set} verb which should be followed directly by the desired value. To read the current value use the verb @option{read}. @option{p} will block if the value of the semaphore would otherwise go below zero. You can also wait for the value of the semaphore to reach zero by using the @option{z} verb. POSIX semaphores does not have built in support for @option{z}, therefore when POSIX semaphores are used, the semaphore will be used as a spinlock. Keep in mind that spinlock are often suboptimal and it can miss that the semaphore's value reaches zero if it for a very short amount of time. @node Shared Memory @chapter Shared Memory Shared memory are primitives and play well with other programs. Use of shared memory are indicated by the @option{-M} option. Shared memory is a form of abstract file that can be used to store raw data between programs. It is highly recommended to create shared memory before any program starts using it. The key for a System V shared memory is an integer, and the key for a POSIX shared memory is an ASCII string with NUL or slash between 1 character and 254 characters long prefixed with a slash. The following options are recognised for shared memory: @table @option @item -s @itemx --size When you create a shared memory you most specify how large, in bytes, the memory allocation should be. KB, MB, etc. are not recognised, only bytes. @item -l @itemx --length When you read shared memory you can specift how many bytes should be read. If this is left unspecified the entire shared memory, starting at the the selected offset, will be read. @item -o @itemx --offset When reading and writing shared memory, you specify how many bytes into the memory that the reading or writing should take place. By default the offset is zero. @end table To read the shared memory, use the verb @option{read}. To write, use the verb @option{write} followed by the data to write to the memory. @node Mutexes @chapter Mutexes Mutexes are implemented using semaphores. Actually, because of inherit limitations, mutexes are binary semaphores. These are fairly primitive and should hopefully interoperate nicely with other programs. A mutex, with the limitations we have, is a construct that lets you enter are guarded state that not be entered again, even recursively, before it has been left. Use of mutexes are indicated by the @option{-X} option. The key for a ``System V'' mutex is an integer, and the key for a ``POSIX'' mutex is an ASCII string with NUL or slash between 1 character and 254 characters long prefixed with a slash. To enter a guarded state with a mutex, use the verb @option{enter}. Then leave it with @option{leave}. @* @cartouche @example create: s := S(1) enter: P(s) leave: V(s) @end example @end cartouche @node Conditions @chapter Conditions A condition is a mutex with support for signalling. They are implemented using three semaphores. Just like with mutexes, you enter and leave guarded states with conditions. But conditions also allow to temporarily leave this state and wait for a signal continue and the re-enter the guarded state when it is not occupied. A signal, called notification, can only be sent from within a guarded state. Use of conditions are indicated by the @option{-C} option. The key for a ``System V'' condition is a integer-trio delimited by full stops. The key for a ``POSIX'' condition is a juxtaposition of three ASCII strings: no NUL or slash, between 1 character and 254 characters long, and prefixed with a slash. To enter a guarded state with a condition, use the verb @option{enter}. Then leave it with @option{leave}. The verbs @option{wait}, @option{notify} and @option{broadcast} can only be used after @option{enter} has been used but before @option{leave}. @option{wait} temporarily leaves the guarded state and wait for a notification. A notification can be sent with @option{notify}. @option{notify} will send a notify to exactly one waiting peer. If there is not peer waiting, the notification will be stored for the next time @option{wait} is used. @option{notify} cannot block. If you want to send a signal to currently waiting peers you can instead use the verb @option{broadcast}. Alternatively you can use @option{notify all} (two command line arguments) perform a @option{broadcast} if there are any waiting peers, and otherwise @option{wait}. @* @cartouche @example create: (s, c, q) := (S(1), S(0), S(0)) enter: P(s) leave: V(s) wait: V(s), V(c), P(q), P(c), P(s) notify: V(q) broadcast: c.value times: V(q) notify all: max(c.value, 1) times: V(q) @end example @end cartouche @node Barriers @chapter Barriers A barrier is a synchronisation primitive that can be used to make sure the a number of process continue their work at the same time and do not fall out of sync with eachother. A barrier blocks until a select number of processes have reached it and the lets all of those processes continue. It does only have one verb: @option{enter}. The threshold, that is the number of process that are synchronised, is specified by the first non-option argument. If @option{enter} is used, the threshold is specified before @option{enter}. The threshold most be specified both at construction and at usage. Use of barriers are indicated by the @option{-B} option. A ``System V'' barrier is constructed from two semaphores. A ``POSIX'' barrier is constructed from three semaphores. This difference is due to the lack of the @code{Z} for POSIX semaphores. The key for a ``System V'' barrier is a integer-duo delimited by a full stop. The key for a ``POSIX'' barrier is a juxtaposition of three ASCII strings: no NUL or slash, between 1 character and 254 characters long, and prefixed with a slash. @* @cartouche @example [sysv] create: (s, mm c) := (S(threshold), S(1), S(0)) [sysv] enter: P(s), Z(s) P(m), V(c) if c.value = threshold: s.value := threshold c.value := 0 V(m) [posix] create: (x, c, q) := (S(1), S(0), S(0)) [posix] enter: P(x), V(c) if c.value = threshold: V(q, delta = threshold - 1) c.value := 0 V(x) else: V(x), P(q) @end example @end cartouche @node Shared Locks @chapter Shared Locks A shared lock is a mutex support for two types of locks: shared and exclusive. They are implemented using three semaphores. Mutexes are can be reduced from shared lock by only using exclusive locking. Exclusive locking allows only on program to enter a guarded state. Shared locks introduce shared locking works the same why but any number of programs can be in this state concurrently. The purpose of the shared locking is to block exclusive locking. If you for example are reading and writing to a file or shared memory, you would apply an exclusive lock if you want to be able to modify the content of the memory and a shared lock if you only which to be able to read it. This guarantees both that two processes will edit the memory at the same time and cause corruption, and that not process will modify the memory while another process is reading it, while allowing multiple processes to read the memory at the same time. Use of shared locks are indicated by the @option{-L} option. The key for a ``System V'' shared lock is a integer-trio delimited by full stops. The key for a ``POSIX'' shared lock is a juxtaposition of three ASCII strings: no NUL or slash, between 1 character and 254 characters long, and prefixed with a slash. There are four verbs for shared locks: @table @option @item shared lock Apply shared locking. @item exclusive lock Apply exclusive locking. @item shared unlock Release shared locking. @item exclusive unlock Release exclusive locking. @* @end table @cartouche @example create: (x, s, m) := (S(1), S(0), S(1)) shared lock: P(m) if s.value = 0: P(x) V(s), V(m) exclusive lock: P(x) shared unlock: P(m), P(s) if s.value = 0: V(x) V(m) exclusive unlock: V(x) @end example @end cartouche @node Rendezvous @chapter Rendezvous A rendezvous is like barrier, except it is fixed to synchronising two processes. When two processes meet at a rendezvous they exchange a message with eachother. Use of rendezvous are indicated by the @option{-R} option. @option{-R} inherits the @option{-s} and @option{-z} options from @option{-Q}. A ``System V'' rendezvous is constructed from two semaphores and one message queue. A ``POSIX'' rendezvous is constructed from three semaphores and one message queue. This difference is due to POSIX message queues having priorities instead of types for messages. The key for a ``System V'' rendezvous is a integer-trio delimited by full stops. The key for a ``POSIX'' shared lock is a juxtaposition of four ASCII strings: no NUL or slash, between 1 character and 254 characters long, and prefixed with a slash. @* @cartouche @example [sysv] create: (m, i, q) := (S(1), S(0), M()) [sysv] enter: P(m) if i.value = 0: V(i), V(m) send(q, type = 1) receive(q, type = 2) else: P(i), V(m) receive(q, type = 1) send(q, type = 2) [posix] create: (m, i, p, q) := (S(1), S(0), S(0), M()) [posix] enter: P(m) if i.value = 0: V(i), V(m) send(q), P(p) receive(q) else: P(i), V(m) receive(q), V(p) send(q) @end example @end cartouche @node GNU Free Documentation License @appendix GNU Free Documentation License @include fdl.texinfo @bye