2

I have Linux 2 processes.

One of them need to send "signal" to the other.

Using signal() will be more difficult, because I will need to store pid of the server program etc.

I think, I better use shared memory with shm_open + mmap, so I can use it for different communication in the future.

Question is following - lets suppose I have bool variable on the shared memory.

How I did synchronize the server and client? Will atomic work if these are two different processes? If it works - how it will works?

Here is naive code for it:

client

// bool b;
b = true;

server

// bool b;
if (b){
   refresh();
   b = false;
}
Nick
  • 9,962
  • 4
  • 42
  • 80
  • The server code is then checking the variable in a while loop? That could give a lot of headaches, I suppose using sockets or signals because then the threads can sleep while the kernel handles the communication – RoQuOTriX Aug 23 '22 at 13:31
  • A quick way to achieve this is with a file lock, though it may not be the solution with the best performance. – François Andrieux Aug 23 '22 at 13:32
  • 1
    https://stackoverflow.com/a/249072/4342498 – NathanOliver Aug 23 '22 at 13:36
  • @NathanOliver: Named semaphores do register additional global names though (leaving one more global resource you can inadvertently fail to release); an alternative is to put POSIX mutexes in the shared memory itself and make the mutex a process shared mutex, e.g. with [`pthread_mutexattr_setpshared`](https://linux.die.net/man/3/pthread_mutexattr_getpshared) or, more safely, [by setting the attribute on mutex initialization](https://linux.die.net/man/3/pthread_mutexattr_init). That way, the shared memory is the only named resource you need to worry about clearing. Depends on use case of course. – ShadowRanger Aug 23 '22 at 13:50
  • 1
    In general, yes, you can use `std::atomic` types in shared memory, and that is probably what you need here. Using a non-atomic type for `b` is effectively a data race. – Nate Eldredge Aug 23 '22 at 13:57
  • @RoQuOTriX is in a poll() / epoll() / kqueue() loop, but only when there is nothing else to do. – Nick Aug 23 '22 at 14:03
  • @NateEldredge how / will atomic will works in shared memory? Is this documented somewhere? – Nick Aug 23 '22 at 14:05
  • 1
    @Nick: You'd use [placement new](https://stackoverflow.com/q/222557/364696) to construct the `atomic` directly into the already allocated memory. You'd also need to explicitly call the destructor on it when you're done (on systems where `atomic` is lock-free, which is most systems to my knowledge, this isn't strictly necessary I believe, but you'd have to allow for the possibility). `atomic_flag` *is* guaranteed lock-free though, and as such I'm pretty sure it's not necessary to explicitly call its destructor (it's a good idea to do it just for cleanliness, but not needed). – ShadowRanger Aug 23 '22 at 14:23
  • I would strongly recommend looking at `man pthread_condattr_setpshared` and `man pthread_mutexattr_setpshared` and backtracking from there. (Also, maybe remove the C++ tag and add a C or POSIX tag or some such.) As for non-blocking algorithms in shared memory, yes, of course they are feasible, but require (in general) spinning and also a decent idea about memory access (re)ordering and memory barriers, i.e. the same knowledge as single-process multithreading. – Andrej Podzimek Aug 23 '22 at 14:25
  • @AndrejPodzimek - we are speaking about different processes, not threads, right? – Nick Aug 23 '22 at 14:32
  • @ShadowRanger - we are speaking about different processes, not threads, right? Where should I call the d-tor? in the server? Suppose I start the client and server to be missing? – Nick Aug 23 '22 at 14:33
  • @Nick: As a rule, that sort of coordination has to be handled by some other mechanism. Ideally, one of them is responsible for creating the shared memory and performing the initial population before the other connects to it. It's ugly if the two processes are launched entirely independently. Some of this is addressed in the duplicate. Also, just realized, if the atomics aren't lock-free, you can't use them, so make sure to verify the atomic types you need are truly lock-free on the systems you're planning to use. – ShadowRanger Aug 23 '22 at 14:37
  • @Nick When it comes to synchronization, there is no difference between different processes accessing a chunk of common shared memory and different threads accessing … well, the “shared” memory of their common process. The only (formal) difference is the need for the `..._setpshared()` parameter on POSIX synchronization primitives. – Andrej Podzimek Aug 23 '22 at 14:49
  • @Nick: I don't think the use of `std::atomic`s in shared memory is documented explicitly. The C++ standard is what defines `std::atomic`, and it has no concept of processes or `mmap`. And conversely POSIX doesn't get down to the level of memory models in describing its features. But it pretty much has to work on any reasonable platform, assuming, as mentioned, that the atomic types in question are lock-free. – Nate Eldredge Aug 24 '22 at 04:21

0 Answers0