有名訊號量實現消費者生產者問題

BLSxiaopanlaile發表於2017-08-20

/*
名稱:有名訊號量實現消費者生產者問題
說明:本實驗實現的是程式同步中經典的消費者生產者的問題。在本實驗中解決的是生產者消費者在多個緩衝區中涉及的同步和互斥問題。
對於一個緩衝區還是多個緩衝區的問題,其主要區別在於解決方案中是不是該包括互斥部分。
對於一個緩衝區,不需要包括互斥部分,因為只有一個緩衝區,生產者和消費者同步連續執行,不會涉及到競爭緩衝區的問題。(或者說,競爭緩衝區的問題已經在解決生產者和消費者同步的過程中解決了。)而對於多個緩衝區,就涉及到互斥部分,這解決的是N個消費者之間的對緩衝區的互斥訪問(當然還有N個生產者之間的),這就是說,本實驗可以同時執行多個生產者程式和多個消費者程式。(當然,一個緩衝區的問題也可以執行多個生產者和多個消費者,不過沒什麼影響,因為只有一個緩衝區,也即訊號量最大就是1)。
需要說明的是,本實驗的緩衝區是通過共享了int型別的陣列實現的,每次生產或者消費的單位是一個int單元。另外,本實驗共享了相同程式之間共享了讀、寫指標。
由於本人的剛學同步和互斥這一部分,所以程式寫的不是很好。linux下執行程式時,會有上次的訊號量值儲存在共享記憶體空間中(這也可能說明了,共享的訊號量在程式結束後,不會被立即清除)。為了清除這個共享訊號量,本人採取了最極端的做法–重啟linux。

*/

#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h> 
#include <semaphore.h> 
#include <fcntl.h>
#include <errno.h>

#include <string.h>
#include <sys/shm.h>
#include <sys/stat.h>
#include <sys/mman.h>

//建立模式許可權
#define FILE_MODE  (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)


int main(int argc,char **argv)
{
    sem_t *info_full; /* 訊號量info_full用於緩衝區滿*/
    sem_t *info_empty;  /*訊號量info_empty用於緩衝區空*/
    sem_t *lock;        //用於相同程式間的互斥訪問

    int i;
    const int SIZE = 4096;      //共享緩衝區的個數
    const int size = 1;         //共享1個寫指標
    int *wr_count;              //共享寫指標

    int shm_fd;
    int *ptr;               //共享緩衝區的首地址
    int value;
    pid_t pid = getpid(); 


      //建立info_full訊號量,初始值為0,緩衝區為空
    if((info_full = sem_open("full",O_CREAT,FILE_MODE,0)) == SEM_FAILED)
    {
          printf("sem_open %s Error\n",argv[0]);
          exit(-1);
    }    

    //建立info_empty訊號量,初始值為4096,緩衝區為空
    if((info_empty = sem_open("empty",O_CREAT,FILE_MODE,SIZE)) == SEM_FAILED)
    {
          printf("sem_open %s Error\n",argv[0]);
          exit(-1);
    }  

    //建立lock訊號量,初始值為1,表示一開始未上鎖
    if((lock = sem_open("lock",O_CREAT,FILE_MODE,1)) == SEM_FAILED)
    {
          printf("sem_open %s Error\n",argv[0]);
          exit(-1);
    }  

    sem_getvalue(info_empty,&value);
    printf("info_empty value is %d.\n",value);

    sem_getvalue(info_full,&value);
    printf("info_full value is %d.\n",value);

    sem_getvalue(lock,&value);
    printf("lock value is %d.\n",value);


    //建立共享記憶體空間
    /* create the shared memory segment */
    shm_fd = shm_open("buf", O_CREAT | O_RDWR, 0666);
    /* configure the size of the shared memory segment */
    ftruncate(shm_fd,SIZE);
    /* now map the shared memory segment in the address space of the process */
    ptr =(int*) mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (ptr == MAP_FAILED) {
        printf("Map buf failed\n");
        return -1;
    }

    //建立共享寫指標記憶體空間
    /* create the shared memory segment */
    shm_fd = shm_open("wr_count", O_CREAT | O_RDWR, 0666);
    /* configure the size of the shared memory segment */
    ftruncate(shm_fd,size);
    /* now map the shared memory segment in the address space of the process */
    wr_count = (int *)mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (wr_count == MAP_FAILED) {
        printf("Map count  failed\n");
        return -1;
    }

    printf("producer--wr_count:%d\n",*wr_count);

    //*wr_count = 0;    //指向第*p_count個緩衝區

    i = 0;

    while(1)
    {   

        sem_wait(info_empty);   //等待緩衝區空
        sem_wait(lock);


        ptr[*wr_count] = i++;
        *wr_count = *wr_count+1;
        printf("I am the producer %d ,I has produced the %d.\n",pid,i);

        sem_post(lock);
        sem_post(info_full);    //宣佈緩衝區已空

        sleep(3);

    }

    sem_close(info_empty);
    sem_close(info_full);
    //sem_unlink(SEM_INFO);         
    return 0;
}

相關文章