多进程共享内存与信号量进程同步方式

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

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。