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


    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
    
  • 相关阅读:
    js定义一个处理字符串的函数
    linux设置别名
    php对图片加水印--将图片先缩小,再在上面加水印
    php对图片加水印--将文字作为水印加到图片
    虚拟机非正常关闭,里面的服务器重启报错:Error, some other host already uses address
    php对图片加水印--将一张图片作为水印加到另一张图片
    Fatal error: Call-time pass-by-reference has been removed in *****.php on line 18
    php中array_walk() 和 array_map()两个函数区别
    nginx 代理转发 wcf接口
    js 日期格式化
  • 原文地址:https://www.cnblogs.com/ydlme/p/4515554.html
Copyright © 2020-2023  润新知