OS: 生产者消费者问题(二) ---- 系统V IPC通信-信号量和共享内存

在上一篇“OS: 生产者消费者问题(多进程+共享内存+信号量)”中提到的方法二: 如果进程之间并没有父子关系,但是协商好了共享存储的 KEY , 那么在每个进程中,就可以通过 KEY 以及 shmget 函数获得共享存储的 I D , 进而通过 shmat 函数获得共享存储的实际地址,最后访问。

本文采用此种方式进行同步生产者和消费者。

1、头文件myshm.h: 要用到的定义和说明

/*
 * myshm.h
 *
 *  Created on: Aug 3, 2013
 *      Author: root
 */

#ifndef MYSHM_H_
#define MYSHM_H_
#endif /* MYSHM_H_ */

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#include <stdio.h>
#include <string.h>
#define SHMSZ 256

union semun{
    int val;
    struct semid_ds * buf;
    unsigned short * array;
};

void init_a_semaphore(int sid, int semnum, int initval){
    union semun semopts;
    semopts.val = initval;
    semctl(sid, semnum, SETVAL, semopts);
}

int semaphore_P(int sem_id){
    struct sembuf sb;
    sb.sem_num=0;
    sb.sem_op = -1;
    sb.sem_flg = SEM_UNDO;
    if(semop(sem_id, &sb, 1) == -1){
        printf("semaphore_P failed.
");
        return 0;
    }
    return 1;
}

int semaphore_V(int sem_id){
    struct sembuf sb;
    sb.sem_num=0;
    sb.sem_op = 1;
    sb.sem_flg=SEM_UNDO;
    if(semop(sem_id, &sb, 1) == -1){
        printf("semaphore_V failed.
");
        return 0;
    }
    return 1;
}

2、生产者程序productProcess.c:

#include "myshm.h"

int main(){
    char * shm, *s;
    int shmid;
    int producer, consumer, i;
    char readbuf[SHMSZ];

    if((consumer = semget((key_t)1234, 1, IPC_CREAT|0660)) == -1){
        printf("server consumer semget failed.
");
        exit(1);
    }
    init_a_semaphore(consumer, 0, 0);

    if((producer = semget((key_t)5678, 1, IPC_CREAT|0660)) == -1){
        printf("server producer semget failed.
");
        exit(1);
    }
    ///printf("ftok("consumer", 0) = %d", (key_t)1234);
    //printf("ftok("consumer", 0) = %d", (key_t)5678);
    //printf("ftok("consumer", 0) = %d", ftok("consumer", 0));
    //printf("ftok("producer", 0) = %d", ftok("producer", 0));
    init_a_semaphore(producer, 0, 1);

    if((shmid = shmget(ftok("shared",0), SHMSZ, 0666| IPC_CREAT)) == -1){
        printf("server shmget failed.
");
        exit(1);
    }
    if((shm = shmat(shmid, (unsigned char*)0, 0)) == -1){
        printf("server shmat failed.
");
        exit(1);
    }

    for(i=0;;i++){
        printf("Enter text:");
        fgets(readbuf, SHMSZ, stdin);
        semaphore_P(producer);
        printf("process %d enter pv key area", getpid());
        sprintf(shm, "Message %4d from producer %d is "%s"
",i, getpid(), readbuf);
        semaphore_V(consumer);
        if(strcmp(readbuf, "end") == 0){
            break;
        }
    }
    return 0;
}

3、消费者程序ConsumerProcess.c:

#include "myshm.h"

int main(){
    char * shm;
    int shmid;
    int producer, consumer, i;
    if((consumer = semget((key_t)1234, 1, IPC_CREAT|0660)) == -1){
        printf("consumer semget failed.
");
        exit(1);
    }
    //init_a_semaphore(consumer, 0, 1);
    if((producer = semget((key_t)5678, 1, IPC_CREAT|0660)) == -1){
        printf("producer semget failed.
");
        exit(1);
    }
    //init_a_semaphore(producer, 0, 1);

    if((shmid = shmget(ftok("shared", 0), SHMSZ, 0666|IPC_CREAT)) == -1){
        printf("shmget failed
");
        exit(1);
    }
    if((shm = shmat(shmid, (unsigned char *)0, 0)) == -1){
        printf("shmat failed.
");
        exit(1);
    }

    for(i=0;;i++){
        printf("Prepare to get Data from memory
");
        semaphore_P(consumer);
        printf("enter pv key memory
");
        printf("Data received:%s
", shm);

        sleep(1);
        semaphore_V(producer);
        if(strcmp(shm, "end") == 0){
            break;
        }
    }

    semctl(producer, 0, IPC_RMID,0);
    semctl(consumer, 0, IPC_RMID, 0);

    return 1;
}
原文地址:https://www.cnblogs.com/wangle1001986/p/3235046.html