操作系统第六次试验:使用信号量解决进程互斥访问

姓名:张越

学号:201821121006

班级:计算1811

一:选择的问题:

哲学家就餐问题

关于问题的描述:

五个哲学家围在一个圆桌就餐,每个人都在思考结束以后进行就餐,但是每个人都必须拿起左右两边的两根筷子才能用餐,当每个人都先拿起左筷子,等待右筷子的时候就会造成死锁。

二:给出伪代码:

思考结束的哲学家饥饿的等待筷子,接着先拿起左边的筷子,再拿起右边的筷子进行进餐。用餐结束以后释放左右筷子,继续进行思考

 

semaphore mutex=1;//互斥地取筷子
semaphore chopstick[5]={1,1,1,1,1}
while(true){      
think();    
wait(chopstick[i]);   //哲学家拿起左边的筷子
wait(chopstick[(i+1)mod 5]);    //哲学家拿起右边的筷子
signal(mutex);     //为了避免同时拿起左边的筷子造成死锁
eat();    
signal(chopstick[(i+1)mod 5]);    //释放右边的筷子
signal(chopstick[i]);      //释放左边的筷子
think();  //接着进行思考 }}

 

  

 

三:给出全部代码

#include<stdio.h>
#include<stdlib.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<sys/types.h>
#include<unistd.h>
#include<errno.h>
#include<sys/ipc.h>
#include<sys/sem.h>
#include<sys/wait.h>

#define ERR_EXIT(m) \
    do { \
        perror(m); \
        exit(EXIT_FAILURE); \
    } while(0)

union semun
{
    int val;    /* Value for SETVAL */
    struct semid_ds *buf;    /* Buffer for IPC_STAT, IPC_SET */
    unsigned short  *array;  /* Array for GETALL, SETALL */
    struct seminfo  *__buf;  /* Buffer for IPC_INFO (Linux-specific) */
};

int semid;

#define DELAY (rand() % 5 + 1)

void wait_for_2fork(int no) //等待进餐 
{
    int left = no;  //哲学家的编号等于左边的叉子编号 
    int right = (no + 1) % 5;  //右边的编号 

    struct sembuf buf[2] =
    {
        {left, -1, 0},
        {right, -1, 0}
    };

    semop(semid, buf, 2);
}

void free_2fork(int no)  //释放资源 
{
    int left = no;
    int right = (no + 1) % 5;

    struct sembuf buf[2] =
    {
        {left, 1, 0},
        {right, 1, 0}
    };

    semop(semid, buf, 2);
}

void philosopere(int no)
{
    srand(getpid());
    for (; ;)
    {

        printf("哲学家%d is thinking\n", no);
        sleep(DELAY);
        printf("哲学家%d is hungry\n", no);
        wait_for_2fork(no);   //拿起一个叉子,等待另外一个 
        printf("哲学家%d is eating\n", no);
        sleep(DELAY);
        free_2fork(no);
    }
}


int main(void)
{

    semid = semget(IPC_PRIVATE, 5, IPC_CREAT | 0666);
    if (semid == -1)
        ERR_EXIT("semget");
    union semun su;
    su.val = 1;
    int i;
    for (i = 0; i < 5; i++)
    {
        semctl(semid, i, SETVAL, su);
    }

    int no = 0;
    pid_t pid;
    for (i = 1; i < 5; i++)
    {
        pid = fork();
        if (pid == -1)
            ERR_EXIT("fork");

        if (pid == 0)
        {
            no = i;
            break;
        }
    }

    philosopere(no);

    return 0;
}

四;运行结果部分截图:

程序一直在运行,说明并没有造成死锁

五:结果分析:

哲学家就餐图:

在一开始的时候,所有的哲学家都是在思考状态,接着2号饿了,2号哲学家进行就餐。接着1号3号4号都等待就餐,但是因为2号哲学家正在使用1,2号筷子,所以哲学家1号跟3号缺乏左边的筷子没有办法就餐,就处于等待状态,4号哲学家开始就餐。等到2号哲学家就餐结束释放资源(筷子),1号哲学家就开始就餐。以此类推。

由此可以看出,位置相邻的哲学家不能同时进餐。

posted on 2020-05-29 21:57  huluntunzao  阅读(241)  评论(0编辑  收藏  举报