有名訊號量實現讀者-寫者問題(讀者優先)

BLSxiaopanlaile發表於2017-08-24

/*
名稱:有名訊號量實現讀者-寫著問題(讀者優先)
說明:本實驗實現的是讀者優先的讀者寫者問題,即若有讀者正在訪問檔案,而且還有讀者和想要申請訪問檔案,則對於讀者可以直接訪問,對於寫者必須等待所有的讀者訪問完畢(包括正在訪問的和正在申請訪問的讀者),沒有讀者時,才能訪問檔案進行寫入。
基本的演算法很簡單,就不說了。要提到一點的是,本實驗花了好幾天時間才弄出來,原因是C掌握不熟,把共享的字元指標sha_buf = “helloworld”.直接賦值,然後用通過sprintf修改sha_buf的內容。其實,此時sha_buf指向是一塊字元常量了,不是原來申請的那塊共享記憶體了。大二之後,C語言用的就少了,基本的都忘了。以後得抽空,好好看看C語言了。

*/

讀者:
#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 SIZE 4096
//建立模式許可權
#define FILE_MODE  (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main(int argc,char **argv)
{
    sem_t * mut_cou = NULL;     /* 用於讀者數量的互斥訪問*/
    sem_t * rw = NULL;          //用於讀者和寫著之間互斥訪問共享檔案

    int *rea_cou = NULL;        //共享的變數,用於儲存當前讀者的人數

    char * sha_buf = NULL;      //共享緩衝區,模擬共享檔案

    int shm_fd = 0;         //用於對映共享記憶體

    int wait_time = 0;

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

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



    //建立共享記憶體空間
    /* 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 */
    sha_buf =(char*) mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (sha_buf == MAP_FAILED) {
        printf("Map buf failed\n");
        return -1;
    }

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


    while(1)
    {
        sem_wait(mut_cou);      //申請訪問變數rea_cou(正在讀檔案的人數)

        if(0 == *rea_cou)       //如果當前人數為0,則要申請互斥訊號量rw
            sem_wait(rw);

        ++(*rea_cou);       //讀者+1

        sem_post(mut_cou);      //釋放變數訪問鎖

        printf("I am reader process .My pid is %d.",getpid());
        printf("I am reading the file.And the content is %s\n",sha_buf);

        sem_wait(mut_cou);      //申請訪問變數rea_cou,準備修改rea_cou
        --(*rea_cou);           //讀者-1

        if(0 == (*rea_cou))     //如果是最後一個讀者的話,則釋放共享檔案訪問鎖
            sem_post(rw);

        sem_post(mut_cou);      //釋放變數訪問鎖

        wait_time = rand()%5;
        sleep(wait_time);   //隨機休息

    }



    return 0;
}
寫者:
#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 SIZE 4096
//建立模式許可權
#define FILE_MODE  (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH)

int main(int argc,char **argv)
{
    sem_t * mut_cou = NULL;     /* 用於讀者數量的互斥訪問*/
    sem_t * rw = NULL;          //用於讀者和寫著之間互斥訪問共享檔案

    int *rea_cou = NULL;        //共享的變數,用於儲存當前讀者的人數

    char * sha_buf = NULL;      //共享緩衝區,模擬共享檔案

    int shm_fd = 0;         //用於對映共享記憶體

    int wait_time = 0;

    pid_t pid = getpid();

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

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



    //建立共享記憶體空間
    /* 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 */
    sha_buf =(char*) mmap(0,SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
    if (sha_buf == MAP_FAILED) {
        printf("Map buf failed\n");
        return -1;
    }

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


    sprintf(sha_buf,"%d writer recorded the infomation",pid);       //初始化共享記憶體區域


    while(1)
    {
        sem_wait(rw);       //申請訪問“檔案”

        printf("I am %d writer.I am writing to the file.\n",pid);

        sprintf(sha_buf,"%d writer recorded the infomation",pid);

        sem_post(rw);       //釋放“檔案”

        wait_time = rand()%5;
        sleep(wait_time);   //隨機休息

    }



    return 0;
}

相關文章