[[_TOC_]]

# Real Time IPC Library

This is a library that allows unrelated processes to exchange variables via
shared memory. Typically, this library is used to communicate between processes
that implement different aspects of a control application in context of the
[EtherLab](https://etherlab.org) technology.

An application exports named variables to shared memory. Similarly, it imports
named variables, which are read from shared memory. If all attributes are
correct (element count and data type), these are connected and data is
exchanged. Semaphores protect access to the shared memory areas.

## Version History

- Version 1.0.4

    - Replaced mhash library with zlib.
      It was used to check the shared memory data structure for changes. Since
      it was not available on modern distributions any more, we switched to
      the crc32 implementation from zlib.

- Version 1.0.3

    - Critical logs are output to stderr by default
    - Control log level via `RTIPC_LOG_LEVEL`

- Version 1.0.2

    - Fixed hashing multiple unused signals
    - Detach shared memory and release exclusive lock in `rtipc_exit()`

- Version 1.0.1

    - Removed libccgnu2 dependency

- Version 1.0.0

    - Added symbol versioning and set SOVERSION to 1.
    - Baked in version information
    - Added symbol visibility macros

## Interface and Workflow

The library has a relatively simple interface:

1) Open a handle to the library using `rtipc_create()`
2) Create one or more groups using `rtipc_create_group()`
3) Register input and output variables using `rtipc_txpdo()` and
   `rtipc_rxpdo()`

> [!note]
> At this stage, the user could call `mlockall()` to lock subsequent memory so
> that it is not swapped any more. The library itself does not rely on this,
> however.

4) Let the library setup its internal structures using `rtipc_prepare()`

> [!note]
> Now the user is ready for the cyclic part

5) Read all input variables from shared memory using `rtipc_rx()`
6) After calculation, write all output variables to shared memory using
        `rtipc_tx()`. Repeat with step 5.

7) When finished, optionally call `rtipc_exit()`

That is it. For more details, see the [header file rtipc.h](include/rtipc.h) or
the [test application](test/).

## The Bulletin Board Directory

An RtIPC instance stores its state in the so-called bulletin board directory.
The location of this directory is determined by the following configuration
options:

- The second parameter (`cache_dir`) of `rtipc_create()`,
- or the environment variable `RTIPC_CACHE`

If none of the above option is used, the directory defaults to
`CMAKE_INSTALL_FULL_LOCALSTATEDIR` (see `CMAKE_INSTALL_PREFIX` and
`LOCALSTATEDIR` in CMake configuration), appended with `/lib/rtipc`, so
typically `/var/lib/rtipc`.

## Logging

Per default, RtIPC outputs critical log messages to the standard error channel.
It can be configured to output more messages via the environment variable
`RTIPC_LOG_LEVEL`. There are three levels:

: 0) Critical (default)
: 1) Notice
: 2) Debug

## Caveats

This is not all, as you might have suspected. There are some subtle aspects to
point out.

### Chicken-egg-problem

What happens when one application exports variables required by a second
application, which in turn exports variables required by the first?

Well, when an application starts, it creates a configuration file with all its
exported variables in the [bulletin board
directory](#the-bulletin-board-directory). Thus applications require write
access to this directory.

If an input variable does not exist at the time the application is started,
start the second application after the first. This sets up the
configuration file with its exported variables. Now restart the first
application and the variables will be connected.

Once the configuration file has been created, an application importing
variables from another is capable opening all the required shared memory
segments and semaphores in its name. When the other application starts, it
will see that all the required structures are already in place and uses
them if the configuration file is compatible with its own configuration.
That is, when the own configuration is a subset of those in the
configuration file, all other attributes being equal.

If the configuration file is incompatible, it is updated, the shared memory
segments and semaphores are removed and setup again. Other applications
using variables exported by this application have to be restarted.

### Shared Memory Management

This raises the issue of who manages the shared memory and semaphores. The
simple answer is: you!

The shared memory and semaphores have to exist even after the application
exits, preventing segmentation violations in other applications. There is
no way to figure out reliably how many applications use these data
structures.

The amount of memory required is usually not much and are recycled every
time. If you are offended, remove them by hand using

- `ipcs`
- `ipcrm -m <shm key>`
- `ipcrm -s <sem key>`

### Cleaning up

From time to time, cleanup the files in the [bulletin board
directory](#the-bulletin-board-directory).
