操作系统第6次实验报告:使用信号量解决进程互斥访问

时间:2020-05-30
本文章向大家介绍操作系统第6次实验报告:使用信号量解决进程互斥访问,主要包括操作系统第6次实验报告:使用信号量解决进程互斥访问使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

姓名:张一鸣

学号:201821121050

班级:计算1812

一、实验目的

通过编程进一步了解信号量。

二、实验内容

在服务器上用Vim编写一个程序:使用信号量解决任一个经典PV问题,测试给出结果,并对解释运行结果。

  • 生产者-消费者问题
  • 读者-写者问题
  • 哲学家进餐问题

三、实验报告

1. 选择哪一个问题

哲学家进餐问题

2. 给出伪代码

semaphore chop[5];
void main(){
    chop[5]={1,1,1,1,1};
    parbegin(Philosopher(i)(i=0...4));
}

void Philosopher(i){
    do{
        thinking;
        wait(chop[i]);
        wait(chop[i+1]mod5);
        eating;
        signal(chop[i]);
        signal)chop[i+1]mod5);
       }while(1);
}

为了避免死锁,仅当哲学家左右两侧的筷子都可用时,才允许他一次性同时拿起两只筷子。

semaphore chop[5]; 
void main(){
    chop[5]={11111}; 
    parbegin(Philosopher(i)(i=0...4));
}

void Philosopher(i) 
{ 
    do { 
        thinking; 
        Swait(chopstick[(i+1)]mod5,chop[i]); 
        eating; 
        Ssignal(chopstick[(i+1)]mod5,chop[i]); 
    }while(1);
}

3. 给出完整代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/wait.h>


union semun
{
    int val;
    struct semid_ds *buf;
    unsigned short *array;
    struct seminfo *__buf;
};


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



int    wait_1fork(int no,int semid)
{
   
    struct sembuf sb = {no,-1,0};
    int ret;
    ret = semop(semid,&sb,1);
    if(ret < 0) {
        ERR_EXIT("semop");
    }
    return ret;
}


int free_1fork(int no,int semid)
{
    struct sembuf sb = {no,1,0};
    int ret;
    ret = semop(semid,&sb,1);
    if(ret < 0) {
        ERR_EXIT("semop");
    }
    return ret;
}



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


void wait_for_2fork(int no,int semid)
{
   
    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 semid)
{
    int left = no;
    int right = (no + 1) % 5;
    struct sembuf buf[2] = {
        {left,1,0},
        {right,1,0}
    };
    semop(semid,buf,2);
}



void philosophere(int no,int semid)
{
    srand(getpid());
    
    for(;;)
    {
    #if 1
     
        printf("%d is thinking\n",no); 
        sleep(DELAY);
        printf("%d is hungry\n",no); 
        wait_for_2fork(no,semid);
        printf("%d is eating\n",no); 
        sleep(DELAY);
        free_2fork(no,semid);
    #else
      
        int left = no;
        int right = (no + 1) % 5;
        printf("%d is thinking\n",no);  
        sleep(DELAY);
        printf("%d is hungry\n",no);   
        wait_1fork(left,semid);   
        sleep(DELAY);
        wait_1fork(right,semid);   
        printf("%d is eating\n",no);  
        sleep(DELAY);
        free_1fork(left,semid); 
        free_1fork(right,semid);  
    #endif
    }
}


int main(int argc,char *argv[])
{
    int semid;
  
    semid = semget(IPC_PRIVATE,5,IPC_CREAT | 0666);
    if(semid < 0) {
        ERR_EXIT("semid");
    }
    union semun su;
    su.val = 1;
    int i;
    for(i = 0;i < 5;++i) {
       
        semctl(semid,i,SETVAL,su);
    }
   
    int num = 0;
    pid_t pid;
    for(i = 1;i < 5;++i)
    {
       pid = fork();
       if(pid < 0)
        {
           ERR_EXIT("fork");
        }
        if(0 == pid)  
        {
            num = i;
            break;
        }
    }
    
   philosophere(num,semid);
    return 0;
}

4. 运行结果并解释

五个哲学家的编号为0~4

一开始,所有哲学家都处于思考状态

3号哲学家饥饿,此时其左右两边的筷子均可用,于是3号哲学家开始进餐

2号哲学家饥饿,但由于3号哲学家拿走了其右手边的筷子并且没有释放,于是2号哲学家保持饥饿状态

1号哲学家饥饿,此时其左右两边的筷子均可用,于是1号哲学家开始进餐

......

原文地址:https://www.cnblogs.com/zhangfengfang/p/12994150.html