操作系统第6次实验报告:使用信号量解决进程互斥访问
时间:2020-05-30
本文章向大家介绍操作系统第6次实验报告:使用信号量解决进程互斥访问,主要包括操作系统第6次实验报告:使用信号量解决进程互斥访问使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
- 姓名:白晓
- 学号:201821121035
- 班级:计算1812
1. 选择哪一个问题
- 哲学家进餐问题
五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在桌子上有五只碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐毕,放下筷子继续思考。
2. 给出伪代码
给出伪代码,并解释算法思想。
semaphore fork[5]={1, 1,1,1,1}; semaphore room=4; void philosopher(int i) { while[(true) { think(); wait(room); /*请求进入房间进餐*/ wait(fork[i); /*请求左手边的筷子*/ wait(fork[(i+ 1)%5]);/*请求右手边的筷子*/ eat(); signal(fork[(i+ 1)%5]); //释放右手边的筷子 signal(fork[i]); //释放左手边的筷子 signal(room); //退出房间释放信号量room } }
在某一个瞬间, 所有的哲学家都同时启动这个算法,拿起左侧的筷子,而看到右侧筷子不可用,又都放下左侧筷子,等一会儿,又同时拿起左侧筷子.....如此这样永远重复下去。对于这种情况,所有的哲学家都吃不上饭,所以至多只允许四个哲学家同时进餐,以保证至少有一个哲学家能够进餐,最终总会释放出他所使用过的两支筷子,从而可使更多的哲学家进餐。
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) //相当于p操作 int wait_1chopstick(int no,int semid) { struct sembuf sb = {no,-1,0}; int ret= semop(semid,&sb,1); //semop()系统调用在semid标识的信号量集中的信号量上执行一个或者多个up/down操作,用于进程间的同步或互斥 if(ret < 0) { ERR_EXIT("semop"); } return ret; }//相当于v操作 int free_1chopstick(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) //相当于p操作 void wait_for_2chopstick(int no,int semid){ //哲学家左边的筷子号数 int left = no; //右边的筷子 int right = (no+1) % 5; //筷子值为2,第一个参数为编号 struct sembuf buf[2] = { {left,-1,0}, //左右两只筷子都能用时才进餐 {right,-1,0} };//信号集中有5个信号量,只是对其中的资源sembuf进行操作 semop(semid,buf,2); }//相当于V操作 void free_2chopstick(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 思考中\n",no); sleep(DELAY); printf("%d 饿了\n",no); wait_for_2chopstick(no,semid);//拿到筷子才能吃饭 printf("%d 进餐中\n",no); sleep(DELAY); free_2chopstick(no,semid);//释放筷子 #else //可能会造成死锁 int right = (no + 1) % 5; printf("%d 思考中\n",no); sleep(DELAY); printf("%d 饿了\n",no); wait_1chopstick(left,semid); sleep(DELAY); wait_1chopstick(right,semid); printf("%d 进餐中\n",no); sleep(DELAY); free_1chopstick(left,semid); free_1chopstick(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);//semctl()系统调用在一个信号量集或集合中的单个信号量上执行各种控制操作 } //创建4个子进程 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);//num 代表进程号 return 0; }
4. 运行结果并解释
分析:一共有五位哲学家,一开始五位哲学家都在思考,过了一段时间哲学家饿了,如果两边筷子都可以使用,就可以进餐,如果有一边的筷子正在被使用则该哲学家需要等待无法就餐,所以相邻的两位哲学家不能同时用餐。
原文地址:https://www.cnblogs.com/muche/p/12993759.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- python基础 -- 异常处理try的使用及一些思考
- 记一次关于MySQL与PHP的蠢事
- 编写一个简单的JQuery插件
- Spring AOP异常:Error creating bean with name ‘org.springframework.aop.aspectj.
- Tomcat7 Redis Session 共享
- CodeIgniter (CI) 框架学习 -- load_class
- Laravel框架学习 -- php artisan down/up
- Spring中基于注解@AspectJ的AOP实现
- python提高--running-python-code-contained-in-a-strin
- linux shell 监控脚本 及 邮件发送
- Laravel框架学习 -- 安装
- Redis 键管理与小功能
- redis 数据持久化
- 不蒜子 | 给网站、博客文章添加阅读次数统计,我用两行代码 搞定计数
- redis 主从复制