多进程共享内存与信号量进程同步方式
shdata.h
#include <mutex> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <stdio.h> #include <string.h> #include <cassert> using std::mutex; struct Person { char name[256]; int age; Person(const char* name, int age); }; #define IPCKEY 0x111 Person::Person(const char* name, int age) { strcpy(this->name, name); this->age = age; } typedef Person DataType; class Shmman { private: DataType* map_ptr_; key_t ipc_key_; size_t buf_size_; int shm_id_; mutex mtx_inner_; bool init(size_t buf_size, int mod_flags); Shmman(const Shmman& chs); public: bool write(DataType* dataptr); void read(); Shmman(key_t ipc_key, size_t buf_size, int mod_flags); ~Shmman(); }; Shmman::~Shmman() { shmctl(shm_id_, IPC_RMID, 0); } Shmman::Shmman(key_t ipc_key, size_t buf_size, int mod_flags) { ipc_key_ = ipc_key; shm_id_ = -1; buf_size_ = buf_size; map_ptr_ = NULL; init(buf_size, mod_flags); } bool Shmman::init(size_t buf_size, int mod_flags) { if (ipc_key_ == -1) { printf("init failed: invalid ipc_key_(-1)!\n"); return false; } shm_id_ = shmget(ipc_key_, buf_size, mod_flags); assert(shm_id_ != -1); if (shm_id_ == -1) { printf("shmget failed: shm_id_(-1)\n"); return false; } map_ptr_ = (DataType*)shmat(shm_id_, 0, 0); assert(map_ptr_ != NULL); return true; } bool Shmman::write(DataType* dataptr) { if (dataptr == NULL) { printf("Shmman::write failed: dataptr is NULL\n"); return false; } if (map_ptr_ == NULL) { printf("Shmman::write failed: map_ptr_ is NULL!\n"); return false; } #ifdef INNERLOCK mtx_inner_.lock(); #endif strcpy(map_ptr_->name, dataptr->name); map_ptr_->age = dataptr->age; #ifdef INNERLOCK mtx_inner_.unlock(); #endif return true; } void Shmman::read() { if (map_ptr_ == NULL) { printf("Shmman::read failed: map_ptr_ is NULL\n"); return; } #ifdef INNERLOCK mtx_inner_.lock(); #endif printf("%s pid:%d\n", map_ptr_->name, map_ptr_->age); #ifdef INNERLOCK mtx_inner_.unlock(); #endif }
executor.cc
#include <unistd.h> #include <sys/wait.h> #include <sys/sem.h> #include "shdata.h" union semun { int val; struct semid_ds* buf; unsigned short int* array; struct seminfo* __buf; }; void pv(int semid, int op) { struct sembuf sem_buf; sem_buf.sem_num = 0; sem_buf.sem_op = op; sem_buf.sem_flg = SEM_UNDO; semop(semid, &sem_buf, 1); } //#define INNERLOCK int main(int argc, const char** argv) { key_t ipc_key = ftok("/tmp", IPCKEY); if (ipc_key == -1) { printf("ftok error\n"); return -1; } size_t buf_size = 4096; int mod_flags = IPC_CREAT | IPC_EXCL | 0600; Shmman* shmman = new Shmman(ipc_key, buf_size, mod_flags); int semid = semget(IPC_PRIVATE, 1, 0666); union semun sem_un; sem_un.val = 1; semctl(semid, 0, SETVAL, sem_un); pid_t pid; int i = 0; const int nprocess = 8; for ( ; i < nprocess; i++) { pid = fork(); if (pid == 0) break; } if (pid < 0) { printf("fork failed\n"); return -1; } else if (pid == 0) { char msg[256]; pid_t cur = getpid(); sprintf(msg, "卧槽尼玛:%d", cur); DataType data(msg, cur); #ifndef INNERLOCK pv(semid, 1); #endif shmman->write(&data); #ifdef INNERLOCK pv(semid, -1); #endif return 0; } else { pid_t pid_chd; int cnt = 0; printf("wait for child process ternimal\n"); while (true) { pid_chd = waitpid(-1, 0, WNOHANG); if (pid_chd > 0) cnt++; if (cnt == nprocess) break; #ifndef INNERLOCK pv(semid, 1); #endif shmman->read(); #ifndef INNERLOCK pv(semid, -1); #endif } printf("%d child process ternimated\n", cnt); delete shmman; semctl(semid, 0, IPC_RMID, sem_un); return 0; } }
Makefile 文件:
CC=clang++-3.5 CXXFLAGS=-std=c++11 main : executor.o $(CC) executor.o -o main executor.o : executor.cc shdata.h $(CC) -c executor.cc shdata.h $(CXXFLAGS) rest : ipcs | grep 4096 | cut -c 12-18 | xargs ipcrm -m clean : rm main *.o *.gch
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。