信號量實現生產者消費者問題


  生產消費問題是一個經典的數學問題,要求生產者---消費者在固定的倉庫空間條件下,生產者每生產一個

產品將占用一個倉庫空間,生產者生產的產品庫存不能越過倉庫的存儲量,消費者每消費一個產品將增加

一個倉庫空間,消費者在倉庫產品為0時不能再消費。

   以下使用了兩個信號量,一個用來管理消費者即sem_produce,另一個用來管理生產者即sem_custom,

sem_produce表示當前倉庫可用空間的數量,sem_custom用來表示當前倉庫中產品的數量。

  • 對於生產者來說,其需要申請的資源為倉庫中的剩余空間,因此,生產者在生產一個產品前需要申請

sem_produce信號量。當此信號量的值大於0,即有可用空間,將生產產品,並將sem_produce的值減去1

(因為占用了一個空間);同時,當其生產一個產品后,當前倉庫的產品數量增加1,需要將sem_custom信號

量自動加1。

  • 對於消費者來說,其需要申請的資源為倉庫中的產品,因此,消費者在消費一個產品前將申請sem_cu

stom信號量。當此信號量的值大於0時,即有可用產品,將消費一個產品,並將sem_custom信號量的值減

去1(因為消費了一個產品);同時,當消費一個產品,當前倉庫的剩余空間增加1,需要將sem_produce信號

量自動加1。

  下面是生產者端的代碼:

//sem_productor.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/sem.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>

int sem_id;
void init()
{
    key_t key;
    int ret;
    unsigned short sem_array[2];
    union semun
    {
        int val;
        struct semid_ds *buf;
        unsigned short *array;
    }arg;
    key= ftok("mysem",'s');
    sem_id= semget(key,2,IPC_CREAT|0644);
    sem_array[0]= 0;
    sem_array[1]= 100;
    arg.array= sem_array;
    ret= semctl(sem_id,0,SETALL,arg);
    if(ret== -1)
    {
        printf("SETALL failed (%d)\n",errno);
    }
    printf("productor init is %d\n",semctl(sem_id,0,GETVAL));
    printf("space init is %d\n\n",semctl(sem_id,1,GETVAL));
}

void del()
{
    semctl(sem_id,0,IPC_RMID);
}

int main(int argc,char *argv[])
{
    struct sembuf sops[2];
    sops[0].sem_num= 0;
    sops[0].sem_op= 1;
    sops[0].sem_flg= 0;

    sops[1].sem_num= 1;
    sops[1].sem_op= -1;
    sops[1].sem_flg= 0;
    init();
    printf("this is productor\n");
    while(1)
    {
        printf("\n\nbefore produce:\n");
        printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
        printf("space number is %d\n",semctl(sem_id,1,GETVAL));
        semop(sem_id,(struct sembuf*)&sops[1],1);
        printf("now producing...\n");
        semop(sem_id,(struct sembuf*)&sops[0],1);
        printf("\nafter produce\n");
        printf("space number is %d\n",semctl(sem_id,1,GETVAL));
        printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
        sleep(2);
    }
    del();
    return 0;
}

   下面是消費者端的代碼:

//sem_customer.c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>

int sem_id;
void init()
{
    key_t key;
    key=ftok("mysem",'s');
    sem_id= semget(key,2,IPC_CREAT|0644);
}

int main(int argc,char *argv[])
{
    struct sembuf sops[2];
    sops[0].sem_num= 0;
    sops[0].sem_op= -1;
    sops[0].sem_flg= 0;

    sops[1].sem_num= 1;
    sops[1].sem_op= 1;
    sops[1].sem_flg= 0;
    init();
    printf("this is customer\n");
    while(1)
    {
        printf("\n\nbefore consume:\n");
        int ret= semctl(sem_id,0,GETVAL);
        int ret1= semctl(sem_id,1,GETVAL);
        printf("productor is %d\n",ret);
        printf("space is %d\n",ret1);
        semop(sem_id,(struct sembuf*)&sops[0],1);
        printf("now consuming...\n");
        semop(sem_id,(struct sembuf*)&sops[1],1);
        printf("\nafter consume\n");
        printf("productor number is %d\n",semctl(sem_id,0,GETVAL));
        printf("space number is %d\n",semctl(sem_id,1,GETVAL));
        sleep(3);
    }
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM