cmdipc -- System V and POSIX IPC from the command line
******************************************************

Copyright © 2014 Mattias Andrée

     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''.

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 mutexe, conditions, barriers, shared locks and rendezvous.

Invoking
********

cmdipc have support for eight types of interprocess communication units: message queues, semaphores, shared memory, mutexe (Because of the nature of this program mutexe are as 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 -P (--posix).

-Q
--mqueue
     Message queue.

-S
--semaphore
     Semaphore.

-M
--shm
     Shared memory.

-X
--mutex
     Mutually exclusive. (Mutex)

-C
--condition
     Condition.

-B
--barrier
     Barrier.

-L
--shared-lock
     Shared lock.

-R
--rendezvous
     Rendezvous.

To specify which instance of a unit to use, specify its key (not ID) with the -k (--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 -c (--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 -x (--exclusive). -x can be used with or without -c, it is interpretation will does not depend on -c, -c is implied by -x. To remove a key, use the option -r (--remove).

There are two additional options that are recognised. These cannot be used with any other optios.

-h
--help
     Print a list of all options.

-f
--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.

The following options are recognised for interprocess communication units.

-n
--nonblocking
     Fail with exit value 2 if the unit is currently occupied and cannot be used without waiting. Not available for shared memory.

-b
--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 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.

-m
--mode OCTAL
     Permission bits for the created unit.

Message Queues
**************

Message queues are primitives and play well with other programs. Use of message queues are indicated by the -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:

-s
--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.

-t
--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.

Recognised options for POSIX message queues:

-s
--size SIZE
     The maximum size of messages in the queue.

-z
--spool SIZE
     The size of the queue. This is the number of messages that can be fit into the queue before it starts blocking.

-p
--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.

To receive a message, add the verb receive. To send a message, add the verb send followed by the message to send.

Semaphores
**********

Semaphores are primitives and play well with other programs. Use of semaphores are indicated by the -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:

-i
--initial VALUE
     You can select the value a semaphore should have when it is created. By default the value is zero.

-d
--delta DIFFERENCE
     When increasing or decreasing the value of the semaphore --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.

The verbs v and 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 set verb which should be followed directly by the desired value. To read the current value use the verb read. 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 z verb. POSIX semaphores does not have built in support for 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.

Shared Memory
*************

Shared memory are primitives and play well with other programs. Use of shared memory are indicated by the -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:

-s
--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.

-l
--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.

-o
--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.

To read the shared memory, use the verb read. To write, use the verb write followed by the data to write to the memory.

Mutexe
******

Mutexe are implemented using semaphores. Actually, because of inherit limitations, mutexe 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 mutexe are indicated by the -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 enter. Then leave it with leave.

     create:
         s := S(1)

     enter:
         P(s)

     leave:
         V(s)

Conditions
**********

A condition is a mutex with support for signalling. They are implemented using three semaphores. Just like with mutexe, 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 -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 enter. Then leave it with leave. The verbs wait, notify and broadcast can only be used after enter has been used but before leave. wait temporarily leaves the guarded state and wait for a notification. A notification can be sent with notify. 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 wait is used. notify cannot block. If you want to send a signal to currently waiting peers you can instead use the verb broadcast. Alternatively you can use notify all (two command line arguments) perform a broadcast if there are any waiting peers, and otherwise wait.

     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)

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: enter. The threshold, that is the number of process that are synchronised, is specified by the first non-option argument. If enter is used, the threshold is specified before enter. The threshold most be specified both at construction and at usage. Use of barriers are indicated by the -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 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.

     [sysv] create:
         (s, m) := (S(threshold), S(1))

     [sysv] enter:
         P(s), Z(s)
         P(m)
         if s.value = 0:
             s.value := threshold
         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)

Shared Locks
************

A shared lock is a mutex support for two types of locks: shared and exclusive. They are implemented using three semaphores. Mutexe 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 -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:

shared lock
     Apply shared locking.

exclusive lock
     Apply exclusive locking.

shared unlock
     Release shared locking.

exclusive unlock
     Release exclusive locking.

     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)

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 -R option. -R inherits the -s and -z options from -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.

     [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)

GNU Free Documentation License
******************************

     [file fdl.texinfo not included]