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)!
");
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)
");
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
");
return false;
}
if (map_ptr_ == NULL) {
printf("Shmman::write failed: map_ptr_ is NULL!
");
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
");
return;
}
#ifdef INNERLOCK
mtx_inner_.lock();
#endif
printf("%s pid:%d
", 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
");
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
");
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
");
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
", 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