My application needs to store and exchange some (one) values between different processes. Also behind a start of the application this value is needed (but not behind a system reboot).
I can write and read this value in a file and synchronize the access. The file could lay in a ramfs. The solution would work but I have the feeling I use the wrong method.
Is there a better lightweight solution for this? Do I miss an straightforward approach?
I was thinking about named pipes (mkfifo) but there needs always and active writer and reader?
You are asking about inter-process communication. There are a number of methods for communicating between processes:
Low-level shared memory
Low-level named pipes
Low-level sockets
Remote procedure call mechanisms (DCOM, Corba, ONC RPC, etc.)
REST api
Distributed system frameworks
Which of these will work best for you depends on the complexity of the messages exchanged between processes, the complexity of the overall system, the need for portability, etc.
Shared memory is a very low-level approach and can feel the easiest solution "because it's just bytes in memory addressed by a pointer". However, it's inherently low-level nature makes it also tedious to use. There is no universally agreed upon C++ interface to these facilities, so you are left with low-level C style APIs for accessing and configuring shared memory between processes. There are differences between platforms (POSIX does it one way; Windows does it another).
Boost.Interprocess gives you a portable way to access shared memory mechanisms and aims to make using them simpler.
Related
I want to implement a server for a protocol. For security reasons the parser should be isolated in its own thread from the rest of the program and only a bidirectional channel should be held open for communication.
The parser thread should lose any possibility to modify the other thread's memory and lose its power to do syscalls (using seccomp).
Is there an easy way to achieve this behavior for the parser thread in Rust?
If you're concerned about issues beyond what Rust's strong safety and type system can protect against (e.g. bugs in those, or in third-party libraries etc.) then you really want separate processes rather than just threads; even if you use seccomp on an untrusted thread, at the OS/CPU level it still has full write access to other threads' memory in the same process.
Either way you'll need to write code designed to run in seccomp carefully (for example allocating extra heap memory might not work) - but the good news is that Rust is a great language for having that control!
There's a reasonably useful discussion on seccomp in Rust which has some suggestions.
The best bet looks like gaol from the Servo project, which is a more general process sandbox (including seccomp). There are also some other lower level seccomp wrappers like this one.
I haven't tried any of this yet, so I'd be interested to hear any other viewpoints/experience.
I just read this page of the Boost.Interprocess documentation. It seems to suggest that in order to accommodate the differences among different operating systems and come to some agreement, certain interprocess mechanisms are not implemented with the directly corresponding native mechanism provided by the operating system, but instead emulated using other mechanisms. I'm wondering whether this may impose a considerable performance hit.
The last section on that page is particularly concerning to me, which is cited below
Since each mechanism can be emulated through diferent mechanisms (a
semaphore might be implement using mapped files or native semaphores)
permissions types could vary when the implementation of a named
resource changes (eg.: in Windows mutexes require synchronize
permissions, but that's not the case of files). To avoid this,
Boost.Interprocess relies on file-like permissions, requiring file
read-write-delete permissions to open named synchronization mechanisms
(mutex, semaphores, etc.) and appropiate read or read-write-delete
permissions for shared memory. This approach has two advantages: it's
similar to the UNIX philosophy and the programmer does not need to
know how the named resource is implemented.
Based on this text, I'm guessing that most of the kernel objects provided natively by Windows for interprocess synchronization (e.g, Event, Mutex, Semaphore) are just not used by Boost.Interprocess.
I've seen before that native kernel objects are used.
As I read it, the message speaks of permissions only.
It mentions that this is emulated in case the underlying objects have different access control. It doesn't actually mention how it's emulated.
I have a very simple interface which needs to communicate between processes. It's currently implemented in a very simple manner (all single proc):
bool GetFoo(struct Foo *outFoo);
bool GetBar(struct Bar *getBar);
Such as:
Foo foo;
if (!GetFoo(&foo))
{
ReportError();
}
GetFoo fills out the "Foo" data structure with pure data (that is, no pointers - it's purely blitable data).
I need to convert this in-process function call to be between two processes on the same machine (in this case it's always the same machine). Is there a commonly followed idiom for cross-process calls in C++ on Windows? Is there some kind of intra-process communication supported by Windows? Should I be using shared memory instead?
One note: I don't want to take a dependency on anything other than the Windows APIs if at all possible.
You have many choices, but in my personal experience the most popular/easy to use ones are: sockets & pipes.
See here for all IPC options available for Windows.
I'm not sure what the most common is -- to truly answer that we'd have to have some kind of polling. That said, the most flexible way would probably be to expose the methods via DCOM.
A common method would be RPC, it can be implemented in various ways for instance as Billy mentioned using COM` (or DCOM if the processes are residing on different machines).
Although you may want to think about not doing direct RPC calls and instead have a named pipe between your processes which is used for the communication.
There are a number of ways to communicate between processes on the same computer in Windows. Which one works best depends on the relationship between the two processes. Is one process expected to start the other? In that case an out-of-process COM server would probably work best, since you can restart the other process if it is not already running.
If performance is critical, then shared memory will give you the most control the speed of passing the data between your processes.
One thing to think about is the failure semantics of running multiple processes. What does the calling process do if the callee is not there?
I'm looking for a way to get two programs to efficiently transmit a large amount of data to each other, which needs to work on Linux and Windows, in C++. The context here is a P2P network program that acts as a node on the network and runs continuously, and other applications (which could be games hence the need for a fast solution) will use this to communicate with other nodes in the network. If there's a better solution for this I would be interested.
boost::asio is a cross platform library handling asynchronous io over sockets. You can combine this with using for instance Google Protocol Buffers for your actual messages.
Boost also provides you with boost::interprocess for interprocess communication on the same machine, but asio lets you do your communication asynchronously and you can easily have the same handlers for both local and remote connections.
I have been using ICE by ZeroC (www.zeroc.com), and it has been fantastic. Super easy to use, and it's not only cross platform, but has support for many languages as well (python, java, etc) and even an embedded version of the library.
Well, if we can assume the two processes are running on the same machine, then the fastest way for them to transfer large quantities of data back and forth is by keeping the data inside a shared memory region; with that setup, the data is never copied at all, since both processes can access it directly. (If you wanted to go even further, you could combine the two programs into one program, with each former 'process' now running as a thread inside the same process space instead. In that case they would be automatically sharing 100% of their memory with each other)
Of course, just having a shared memory area isn't sufficient in most cases: you would also need some sort of synchronization mechanism so that the processes can read and update the shared data safely, without tripping over each other. The way I would do that would be to create two double-ended queues in the shared memory region (one for each process to send with). Either use a lockless FIFO-queue class, or give each double-ended queue a semaphore/mutex that you can use to serialize pushing data items into the queue and popping data items out of the queue. (Note that the data items you'd be putting into the queues would only be pointers to the actual data buffers, not the data itself... otherwise you'd be back to copying large amounts of data around, which you want to avoid. It's a good idea to use shared_ptrs instead of plain C pointers, so that "old" data will be automatically freed when the receiving process is done using it). Once you have that, the only other thing you'd need is a way for process A to notify process B when it has just put an item into the queue for B to receive (and vice versa)... I typically do that by writing a byte into a pipe that the other process is select()-ing on, to cause the other process to wake up and check its queue, but there are other ways to do it as well.
This is a hard problem.
The bottleneck is the internet, and that your clients might be on NAT.
If you are not talking internet, or if you explicitly don't have clients behind carrier grade evil NATs, you need to say.
Because it boils down to: use TCP. Suck it up.
I would strongly suggest Protocol Buffers on top of TCP or UDP sockets.
So, while the other answers cover part of the problem (socket libraries), they're not telling you about the NAT issue. Rather than have your users tinker with their routers, it's better to use some techniques that should get you through a vaguely sane router with no extra configuration. You need to use all of these to get the best compatibility.
First, ICE library here is a NAT traversal technique that works with STUN and/or TURN servers out in the network. You may have to provide some infrastructure for this to work, although there are some public STUN servers.
Second, use both UPnP and NAT-PMP. One library here, for example.
Third, use IPv6. Teredo, which is one way of running IPv6 over IPv4, often works when none of the above do, and who knows, your users may have working IPv6 by some other means. Very little code to implement this, and increasingly important. I find about half of Bittorrent data arrives over IPv6, for example.
Suppose I have a daemon that is sharing it's internal state to various applications via shared memory. Processes can send IPC messages to the daemon on a named pipe to perform various operations. In this scenario, I would like to create a C++ wrapper class for clients that acts as a kind of "Remote Proxy" to hide some of the gory details (synchronization, message passing, etc) from clients and make it easier to isolate code for unit tests.
I have three questions:
Generally, is this a good idea/approach?
Do you have any tips or gotchas for synchronization in this setup, or is it enough to use a standard reader-writer mutex setup?
Are there any frameworks that I should consider?
The target in question is an embedded linux system with a 2.18 kernel, therefore there are limitations on memory and compiler features.
Herb Sutter had an article Sharing Is the Root of All Contention that I broadly agree with; if you are using a shared memory architecture, you are exposing yourself to quite a bit of potential threading problems.
A client/server model can make things drastically simpler, where clients write to the named server pipe, and the server writes back on a unique client pipe (or use sockets). It would also make unit testing simpler (since you don't have to worry about testing shared memory), could avoid mutexing, etc.
There's Boost.Interprocess library, though I can't comment on its suitability for embedded systems.