Overview
In this post, I am sharing an example of IPC communication with a class using shared memory.
Two processes runs together, and their applications sequentially running. The end of each loop is marked at a shared memory with a “go-flag”. Once the other process see the end-of-the-loop flag, “go-flag”, the process continues the task.
Shared Memory IPC Class
I wrote this class to make the shared memory programming more portable. What you need to do is only to change the struct called “shared_memory_packet. You will see how to use this class in the examples of the next section. You can see the code of “shared_memory_base.h” and “shared_memory_base.cpp” below:
#ifndef SHARED_MEMORY_BASE_H #define SHARED_MEMORY_BASE_H #include <sys/ipc.h> #include <sys/shm.h> #define DEFAULT_KEY_ID 5700 // default key for shared memory class shared_memory_base { struct shared_memory_packet { float analog_input[16]; bool go_flag_second_loop = 1; bool go_flag_first_loop = 1; }; private: key_t key; int shmid = 0; public: shared_memory_base(); ~shared_memory_base(); shared_memory_packet* data; void init(); void change_shared_memory_key(key_t k){key= k;} // only use this function before init void detach_shared_memory(); }; #endif // SHARED_MEMORY_BASE_H
#include "shared_memory_base.h" shared_memory_base::shared_memory_base() { key = ftok("shmfile",DEFAULT_KEY_ID); } shared_memory_base::~shared_memory_base(){ detach_shared_memory(); } void shared_memory_base::init(){ // shmget returns an identifier in shmid shared_memory_packet temp; shmid = shmget(key, sizeof(temp),0666|IPC_CREAT); // shmat to attach to shared memory data = (shared_memory_packet*) shmat(shmid,(void*)0,0); } void shared_memory_base::detach_shared_memory(){ shmdt(data); shmctl(shmid,IPC_RMID,nullptr); }
Ping-pong Sequence between Two Processes
In this example, “first_app.cpp” the number of an integer variable incrementally, and change the “go_flag_second_loop” to be one. In “second_app.cpp” the number of an integer variable is reduced, and change the “go_flag_first_loop” to be one. With this two go_flags two processes run sequencially.
#include <iostream> #include <unistd.h> #include "shared_memory_base.h" using namespace std; int main() { shared_memory_base comm; comm.init(); comm.data->analog_input[0] =0; comm.data->analog_input[8] =0; for (int i=0;i<10;i++){ while( comm.data->go_flag_first_loop != 1); comm.data->analog_input[0] = i; cout << "ai[8]: " << comm.data->analog_input[8] << endl; comm.data->go_flag_second_loop = 1; sleep(1); } cout << "end of the loop!" << endl; comm.detach_shared_memory(); return 0; }
#include <iostream> #include "shared_memory_base.h" using namespace std; int main() { shared_memory_base comm; comm.init(); comm.data->analog_input[0] =0; comm.data->analog_input[8] =0; comm.data->go_flag_first_loop = 1; for (int i=0;i<10;i++){ while( comm.data->go_flag_second_loop != 1); comm.data->analog_input[8] = 1000-i; cout << "ai[0]: " << comm.data->analog_input[0] << endl; comm.data->go_flag_second_loop = 0; } cout << "end of the loop!" << endl; comm.detach_shared_memory(); return 0; }
Result
The figures below shows the execution results of two applications.
Download and Build the Codes
You can download the entire code and can build the code with the command below:
mkdir build cd build cmake ../shared_memory_example make
More discussion
Concurrency problem is a very well-known and challenging problem. There are many other nice techniques other than this one. Particularly after C++11, the standard C++ has introduced a nice set of concurrent thread and process running functions. In addition, this example is not the best code for efficient applications.
I found a very good reference explaining Concurrency, Parallelism, Threads, Processes, Async and Sync. For the details, read the article in the link below: