POSIX shm

参考

【C言語】親子プロセス間で共有メモリを使う - 意味悲鳴

POSIX / Semapho のメモ

Pthread - Mutexでプロセス間排他制御を行う - s-kitaの日記

送信

#include <stdio.h>
#include <unistd.h>     /* for ftruncate */
#include <sys/mman.h>   /* for shm_open */
#include <sys/stat.h>   /* for *_MODE */
#include <fcntl.h>      /* for O_* */

#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)

#include <pthread.h>

int     EndFlag=0;

int main()
{
//int    id;
int     *adr;
pthread_mutex_t *mtx;

//int   adr;
//key_t key;

        int fd, ret;


        /* 共有メモリ・オブジェクトを作成 */
        fd = shm_open("/shared_memory",  O_RDONLY, FILE_MODE);
        if(fd == -1) {
                perror("shm_open");
                fprintf(stderr, "recv を先に呼んでください\n");
                return 1;
        }
        /* 共有メモリ・オブジェクトを作成 */
        fd = shm_open("/shared_memory",  O_CREAT | O_RDWR, FILE_MODE);
        if(fd == -1) {
                perror("shm_open");
                return 1;
        }

        /* 使用するメモリ領域を拡張 */
        ret = ftruncate(fd, sizeof(int));
        if (ret != 0) {
                /* error handling */
                perror("ftruncate");
                return 1;
        }


        adr = mmap (0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);


        /* mutex */
        fd = shm_open("/shared_memory_mtx",  O_CREAT | O_RDWR, FILE_MODE);
        if(fd == -1) {
                perror("shm_open mtx");
                return 1;
        }

        ret = ftruncate(fd, sizeof(pthread_mutex_t));
        if (ret != 0) {
                /* error handling */
                perror("ftruncate mtx");
                return 1;
        }

        mtx = mmap (0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);


        if(adr == MAP_FAILED) {
                /* error handling */
                perror("mmap");
                return 1;
        } else {
                while(1){
                        sleep(1);
                        pthread_mutex_lock(mtx);

                        printf("*** send1 %d\n", *adr);
                        *adr = *adr + 1;
                        sleep(1);
                        printf("*** send2 %d\n", *adr);
                        *adr = *adr + 1;
                        sleep(1);
                        printf("*** send3 %d\n", *adr);
                        *adr = *adr + 1;

                        pthread_mutex_unlock(mtx);
                }
        }

        ret = shm_unlink("/shared_memory");
        if (ret != 0) {
                /* error handling */
                perror("shm_unlink");
                return 1;
        }
        ret = shm_unlink("/shared_memory_mtx");
        if (ret != 0) {
                /* error handling */
                perror("shm_unlink mtx");
                return 1;
        }

        return(0);
}

受信

#include <stdio.h>      /* for perror */
#include <unistd.h>     /* for ftruncate */
#include <signal.h>
#include <sys/mman.h>   /* for shm_open */
#include <sys/stat.h>   /* for S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH */
#include <fcntl.h>      /* for O_* */

#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)

#include <pthread.h>

int     EndFlag=0;

void sigHandle(int sig)
{
        EndFlag=sig;
}

int main()
{
//int    id;
int     *adr;
pthread_mutex_t *mtx;
pthread_mutexattr_t mattr;
//int   adr;
//key_t key;

        int fd, ret;

        signal(SIGINT,sigHandle);
        signal(SIGTERM,sigHandle);
        signal(SIGQUIT,sigHandle);

        /* 共有メモリ・オブジェクトを作成 */
        fd = shm_open("/shared_memory",  O_CREAT | O_RDWR, FILE_MODE);
        /* O_CREAT: 存在しない場合、共有メモリーオブジェクトを作成する */
        /* O_RDWR : 読み書きアクセス用にオブジェクトをオープンする。 */
        /* O_EXCL : O_CREAT が一緒に指定されており、
          name で指定された共有メモリーオブジェクトが既に存在した場合、 エラーを返す。 */
        if(fd == -1 ) {
                perror("shm_open");
                return 1;
        }
        /* 使用するメモリ領域を拡張 */
        ret = ftruncate(fd, sizeof(int));
        if (ret != 0) {
                /* error handling */
                perror("ftruncate");
                return 1;
        }

        adr = mmap (0, sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
        *adr = 2147483646;

        /* mutex */
        fd = shm_open("/shared_memory_mtx",  O_CREAT | O_RDWR, FILE_MODE);
        if(fd == -1) {
                perror("shm_open mtx");
                return 1;
        }

        ret = ftruncate(fd, sizeof(pthread_mutex_t));
        if (ret != 0) {
                /* error handling */
                perror("ftruncate mtx");
                return 1;
        }
        mtx = mmap (0, sizeof(pthread_mutex_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);

        /* プロセス間排他y用に初期化 */
        pthread_mutexattr_init(&mattr);
        pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);

        ret = pthread_mutex_init(mtx, &mattr);
        if (ret != 0) {
                fprintf(stderr, "pthread_mutex_init error\n");
                return 1;
        }

        if(adr == MAP_FAILED) {
                /* error handling */
                perror("mmap");
                return 1;

        } else if(mtx == MAP_FAILED) {
                /* error handling */
                perror("mmap mtx");
                return 1;
        } else {
                while(1){
                        sleep(1);
                        if(EndFlag!=0){
                                fprintf(stderr,"EndFlag=%d\n",EndFlag);
                                break;
                        }
                        ret = pthread_mutex_lock(mtx);

                        if (ret != 0) {
                                fprintf(stderr, "pthread_mutex_lock error\n");
                        }
                        *adr = *adr - 1;
                        printf("*** decr1 %d\n",*adr);
                        sleep(3);
                        *adr = *adr - 1;
                        printf("*** decr2 %d\n",*adr);
                        sleep(2);

                        pthread_mutex_unlock(mtx);

                        if (ret != 0) {
                                fprintf(stderr, "pthread_mutex_unlock error\n");
                        }

                }
        }

        ret = shm_unlink("/shared_memory");
        if (ret != 0) {
                /* error handling */
                perror("shm_unlink");
                return 1;
        }
        ret = shm_unlink("/shared_memory_mtx");
        if (ret != 0) {
                /* error handling */
                perror("shm_unlink mtx");
                return 1;
        }

        return(0);
}