無名訊號量實現哲學家問題

BLSxiaopanlaile發表於2017-08-21

/*
名稱:無名訊號量實現哲學家問題
說明:本實驗是利用無名訊號量實現哲學家問題。
總體的思路是不讓左右相鄰的哲學家同時申請同一個筷子,即奇數號哲學家先申請位於其 左邊的筷子,然後再申請其右邊的筷子;偶數號科學家先申請右邊的筷子,然後在申請左邊的筷子。以達到同步的目的。
程式整體的流程是:主程式申請了N個無名的訊號量,然後把它們對映到共享記憶體中(因為無名訊號量原本是產生在各自的程式空間中的。)接著,fork生成了N個子程式來模擬N個哲學家的行為。之後主程式進入死迴圈,N個哲學家子程式進行活動。
在實驗中粗心遇到了一個小問題,就是一開始為了方便,把哲學家從一開始編號,訊號量也是從一開始編號,最後程式執行時最後兩個哲學家一直沒反應。好幾天後才想起來,在取餘操作時沒有了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 num_of_phi 5

int main(int argc,char **argv)
{
    sem_t *chopsticks[num_of_phi+1];    /* 訊號量info_full用於緩衝區滿*/


    int i = 0;
    int flag_of_phi = 0;        //哲學家的編號

    int wait_time = 0;      //用於隨機等待一定的時間


    pid_t pid;

    for(i = 0;i<num_of_phi;++i)
    {
        chopsticks[i] = (sem_t*)mmap(NULL,sizeof(sem_t),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);        //將無名訊號量共享


         if (chopsticks[i] == NULL)
        {
            printf("Share memory failed!\n");
            return -1;
        }   
        if (sem_init(chopsticks[i], 1, 1) == -1)    //初始化每個訊號量,初始值為1
        {
            printf("Init unamed sem failed!\n");
            return -1;
        }
    }
        printf("This is the main function.\n");

    i = 0;

    //建立num_of_phi個哲學家程式
    while(1)
    {
        pid = fork();
        //父程式
        ++i;
        if(pid > 0)
        {   
            if(i >= num_of_phi)
            {
                while(1) ;  //如果主程式建立了num_of_phi個程式後,就一直迴圈
            }

        }
        else
        {
            flag_of_phi = i;        //第i個哲學家
            printf("I am the %d philosopher,I was born!\n",flag_of_phi);
            break;      //哲學家程式退出,執行後續程式

        }
    }


    while(1)
    {

         if(flag_of_phi % 2 == 1)   //奇數號哲學家
        {

            sem_wait(chopsticks[flag_of_phi % num_of_phi]);     //等待左邊筷子
            sem_wait(chopsticks[(flag_of_phi+1) % num_of_phi]);     //等待右邊筷子

            printf("I am the %d philosopher,and I am eating.....\n",flag_of_phi);

            sem_post(chopsticks[flag_of_phi % num_of_phi]);     //釋放左邊筷子
            sem_post(chopsticks[(flag_of_phi+1) % num_of_phi]);     //釋放右邊筷子

            printf("I am the %d philosopher,and I am thinking.....\n",flag_of_phi);


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



        }
        else    //偶數號哲學家
        {

            sem_wait(chopsticks[(flag_of_phi+1) % num_of_phi]); //等待右邊筷子
            sem_wait(chopsticks[flag_of_phi % num_of_phi]);     //等待左邊筷子

            printf("I am the %d philosopher,and I am eating.....\n",flag_of_phi);

            sem_post(chopsticks[flag_of_phi % num_of_phi]);     //釋放右邊筷子
            sem_post(chopsticks[(flag_of_phi+1) % num_of_phi]); //釋放左邊筷子

            printf("I am the %d philosopher,and I am thinking.....\n",flag_of_phi);


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


        } 


    }


    return 0;
}

相關文章