0

I am programming a slaightly complex software with multiple multi-threaded processes. Since in one of them I need real-time capabilities (for robustness, basically) I patched my target kernel for Xenomai and programmed it using Xenomai's native skin.

Now I need to communicate two processes: one running real-time tasks and another running simply pthreads (with the latter compiled without Xenomai's real-time libraries/skin).

My question is: can I communicate them somehow? For instance, can I create a shared memory object (shm_open) and share mutexes even if one of them is in the RT environment?

  • If the answer is yes, should I use the POSIX skin in the Xenomai one?
  • If the answer were no, how can I safely share data/communicate them? Named-pipes is the only approach I can think of...
Carles Araguz
  • 1,157
  • 1
  • 17
  • 37
  • 1
    I have worked with rtai, but that shares a history with xenomai. Based on my experience in RTAI, you can't use real-time mutexes in non-real-time threads. You _can_ use non-real-time mutexes in a real-time thread, but that would break the real-time-ness of the thread since control is taken out of the hands of the real-time scheduler and is given to Linux which is run in a non-real-time context. There's no problem with shared memory though (without the synchronization) – Shahbaz Nov 28 '13 at 18:41
  • 1
    Something I have used myself is a kind of circular buffer that is filled by the real-time task whose _last_ index is atomically incremented in the real-time thread and its _first_ index atomically incremented in the non-real-time thread. If the buffer gets full, the real-time thread would overwrite oldest data, but if buffer is big enough that would be very unlikely to happen. – Shahbaz Nov 28 '13 at 18:45

1 Answers1

2

I would suggest you to use Xenomai native API to create Named Pipes, such as rt_pipe_create() and so on.

There is one more thing which you can use: Message Queues. However I have always chosen Named Pipe over Message Queues.

Both shared memory and message queues can be used to exchange information between processes. The difference is in how they are used.

Shared memory is exactly what you'd think: it's an area of storage that can be read and written by more than one process. It provides no inherent synchronization; in other words, it's up to the programmer to ensure that one process doesn't clobber another's data. But it's efficient in terms of throughput: reading and writing are relatively fast operations.

A message queue is a one-way pipe: one process writes to the queue, and another reads the data in the order it was written until an end-of-data condition occurs. When the queue is created, the message size (bytes per message, usually fairly small) and queue length (maximum number of pending messages) are set. Access is slower than shared memory because each read/write operation is typically a single message. But the queue guarantees that each operation will either processes an entire message successfully or fail without altering the queue. So the writer can never fail after writing only a partial message, and the reader will either retrieve a complete message or nothing at all.

Essentially, pipes - whether named or anonymous - are used like message passing. Someone sends a piece of information to the recipient and the recipient can receive it. Shared memory is more like publishing data - someone puts data in shared memory and the readers (potentially many) must use synchronization e.g. via semaphores to learn about the fact that there is new data and must know how to read the memory region to find the information.

With pipes the synchronization is simple and built into the pipe mechanism itself - your reads and writes will freeze and unfreeze the app when something interesting happens. With shared memory, it is easier to work asynchronously and check for new data only once in a while - but at the cost of much more complex code. Plus you can get many-to-many communication but it requires more work again. Also, due to the above, debugging of pipe-based communication is easier than debugging shared memory.

A minor difference is that fifos are visible directly in the file system while shared memory regions need special tools like ipcs for their management in case you e.g. create a shared memory segment but your app dies and doesn't clean up after itself (same goes for semaphores and many other synchronization mechanisms which you might need to use together with shared memory).

Shared memory also gives you more control over buffering and resource use - within limits allowed by the OS it's you who decides how much memory to allocate and how to use it. With pipes, the OS controls things automatically, so once again you loose some flexibility but are relieved of much work.

Summary of most important points: pipes for one-to-one communication, less coding and letting the OS handle things, shared memory for many-to-many, more manual control over things but at the cost of more work and harder debugging

  • Thanks for your kind reply. `shm_open` won't work, then? And what about shared mutexes between Xenomai and non-RT processes? Can they be shared? – Carles Araguz Nov 14 '13 at 16:27
  • @CarlesAraguz: It depends on what is better for you. See the edit –  Nov 15 '13 at 14:44
  • Thanks again for this thorough reply. I really appreciated it! Even though my initial question was whether or not this RT mechanisms can be used to communicate a `pthread` (in a non-RT process) AND a `rt_task`. I am concerned about using these methods in a system that has a dual kernel/scheduler (like Xenomai-Linux). – Carles Araguz Nov 15 '13 at 18:46