Practice: Implement a first in, out shared memory Shmfifo
Message Queuing is used to implement the FIFO of the message, but it is faster to use shared memory for the FIFO of the message;
We first complete the C language version of Shmfifo (based on the procedure call), and then implement the C + + version of Shmfifo on this basis, will be 1 blocks of shared memory with 3 semaphores (1 mutext semaphores, 1 full semaphores, 1 empty semaphores) Encapsulated into a class Shmfifo, and then write their own test code;
Shmfifo Description:
The requested shared memory is used as a buffer, and the header (P_shm to P_payload) of the memory is formatted as shown in the form;
Read/write process constantly in accordance with the principle of cash first out of the read/write data from it, the read/write process can be regarded as producer/consumer, therefore, using the semaphore Sem_mutex (initial value of 1) to mutually exclusive access to shared memory, using Sem_full (initial value is the number of shared buffer blocks), sem_ Empty (initial value is 0) to synchronize two processes.
Version C:
/**shmfifo initialization includes both the initialization of shared memory and the initialization of three semaphores; Tip: First try to open an IPC object, if open fails, it means that the IPC object has not yet been created, you need to create it, and if open succeeds, then do something else **/ shmfifo_t *shmfifo_init (int key, int blksize, int blocks) {shmfifo_t *fifo = (shmfifo_t *) malloc (sizeof (shmfifo_t)); ASSERT (FIFO! = NULL); memset (FIFO, 0, sizeof (shmfifo_t)); Attempt to open shared memory int shmid = Shmget (key, 0, 0); If open fails, indicates that the shared memory has not been created, create if (Shmid = =-1) {/** set shared memory **/int size = blksize*blocks + sizeof (SHMH ead_t); Create shared memory Fifo->shmid = Shmget (key, size, ipc_creat|0666); if (Fifo->shmid = =-1) err_exit ("Shmget error"); To create the shared memory successfully, you need to connect it to the process's address space//void *shmat (int shmid, const void *shmaddr, int shmflg); FIFO->P_SHM = (shmhead_t *) Shmat (fifo->shmid, NULL, 0); if (Fifo->p_shm = = (void *)-1) err_exit ("Shmat error"); Initializes the header of the shared memory to a struct shmhead fifo->p_shm->blksize = blksize; Fifo->p_shm->blocks = Blocks; Fifo->p_shm->rd_index = 0; Fifo->p_shm->wr_index = 0; Fifo->p_payload = (char *) (FIFO->P_SHM+1); /** set three semaphores **/Fifo->sem_mutex = sem_create (key); Sem_setval (Fifo->sem_mutex, 1); Fifo->sem_full = Sem_create (key+1); Sem_setval (Fifo->sem_full, 10); Fifo->sem_empty = Sem_create (key+2); Sem_setval (fifo->sem_empty, 0); } else {fifo->shmid = Shmid; Shared memory already exists and opens successfully, you need to connect it to the process's address space FIFO->P_SHM = (shmhead_t *) Shmat (fifo->shmid, NULL, 0); if (Fifo->p_shm = = (void *)-1) err_exit ("Shmat error"); Fifo->p_payload = (char *) (FIFO->P_SHM+1); /** set three semaphores **/Fifo->sem_mutex = Sem_open (key); Fifo->sem_full = Sem_open (key+1); Fifo->sem_empty = Sem_open (key+2); } return FIFO;}
/** Test code: write.cpp**/struct student{ Char name[32]; int age;}; int main () { shmfifo_t *fifo = shmfifo_init (1234, sizeof (Student), n); Student s; Bzero (&s, sizeof (s)); strcpy (S.name, "Xiaofang"); for (int i = 0; i < ++i) { sprintf (& (S.name[8]), "%d", I); S.age = i; Shmfifo_put (FIFO, &s); cout << "put success" << Endl; }}
/** Test Code: Read.cpp**/int Main () { shmfifo_t *fifo = shmfifo_init (1234, sizeof (Student), 3); Student s; for (int i = 0; i < 5; ++i) { bzero (&s, sizeof (s)); Shmfifo_get (FIFO, &s); printf ("Name:%s, age =%d\n", S.name, S.age); } return 0;}
/** Test code: Destroys the shared memory created with the semaphore, Free**/int Main () { shmfifo_t *fifo = shmfifo_init (1234, sizeof (Student), 3); Shmfifo_destroy (FIFO); return 0;}
Complete C source code:http://download.csdn.net/detail/hanqing280441589/8437855
C + + version:
/** constructor **/shmfifo::shmfifo (int _key, int _blksize, int _blocks) {//Open a piece of shared memory Shmid = Shmget (_key, 0, 0); If the open fails, the shared memory is not created, then the IF (Shmid = =-1) {/** Sets the shared memory **/int size = _blksize*_blocks + sizeof (s hmhead_t); Create shared memory Shmid = Shmget (_key, size, ipc_creat|0666); if (Shmid = =-1) err_exit ("Shmget error"); To create the shared memory successfully, you need to connect it to the process's address space P_SHM = (shmhead_t *) Shmat (shmid, NULL, 0); if (P_shm = = (void *)-1) err_exit ("Shmat error"); Initializes the header of the shared memory to a struct shmhead p_shm->blksize = _blksize; P_shm->blocks = _blocks; P_shm->rd_index = 0; P_shm->wr_index = 0; P_payload = (char *) (P_SHM+1); /** set three semaphores **/Sem_mutex = sem_create (_key); Sem_setval (Sem_mutex, 1); Sem_full = Sem_create (_key+1); Sem_setval (Sem_full, _blocks); Sem_empty = Sem_create (_key+2); Sem_setval (sem_empty, 0); } else { Shared memory already exists and opens successfully, you only need to connect it to the process's address space P_SHM = (shmhead_t *) Shmat (shmid, NULL, 0); if (P_shm = = (void *)-1) err_exit ("Shmat error"); P_payload = (char *) (P_SHM+1); /** Open three semaphores **/Sem_mutex = Sem_open (_key); Sem_full = Sem_open (_key+1); Sem_empty = Sem_open (_key+2); }}/** destructor **/shmfifo::~shmfifo () {SHMDT (P_SHM); Unmount shared Memory P_shm = NULL; P_payload = NULL;}
/** destroy function **/void Shmfifo::d Estroy () { sem_delete (Sem_mutex); Sem_delete (sem_full); Sem_delete (sem_empty); if (Shmctl (Shmid, Ipc_rmid, NULL) = =-1) err_exit ("Remove share memory Error");}
/** put function **/void shmfifo::p ut (const void *buf) { sem_p (sem_full); Sem_p (Sem_mutex); /** enters the critical section **/ //Gets the write position from the structure char *index = p_payload + (P_shm->wr_index * p_shm->blksize); Write memcpy (index, buf, p_shm->blksize); Index shift P_shm->wr_index = (p_shm->wr_index+1)%p_shm->blocks; /** exit Critical Zone **/ Sem_v (Sem_mutex); Sem_v (sem_empty);}
/** Get function **/void shmfifo::get (void *buf) { sem_p (sem_empty); Sem_p (Sem_mutex); /** enters the critical section **/ //obtains the readout position from the structure char *index = p_payload + (P_shm->rd_index * p_shm->blksize); Read memcpy (buf, index, p_shm->blksize); P_shm->rd_index = (p_shm->rd_index+1)%p_shm->blocks; /** exit Critical Zone **/ Sem_v (Sem_mutex); Sem_v (sem_full);}
Complete C + + source code:http://download.csdn.net/download/hanqing280441589/8438025
Attached-makefile, two programs can use the file
. Phony:clean ALLCC = g++cppflags =-wall-gbin = Write Read freesources = $ (bin.=.cpp) All: $ (BIN)%.O:%.cpp$ (CC) $ (cppflag S)-C $^-o [email protected]write:write.o shmfifo.o ipc.o$ (CC) $ (cppflags) $^-lrt-o [email protected]read:read.o SHMF IFO.O ipc.o$ (CC) $ (cppflags) $^-lrt-o [email protected]free:free.o shmfifo.o ipc.o$ (cc) $ (cppflags) $^-lrt-o [email p ROTECTED]CLEAN:-RM-RF $ (BIN) *.O Bin/obj/core
Linux IPC Practice (--system V IPC Integrated Practice)