0 个人信息

张樱姿

201821121038

计算1812

1 实验目的

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

2 实验内容

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

3 实验报告

3.1 选择哲学家进餐问题

五个哲学家共用一张圆桌,分别坐在周围的五张椅子上,在圆桌上有五个碗和五只筷子,他们的生活方式是交替地进行思考和进餐。平时,一个哲学家进行思考,饥饿时便试图取用其左右最靠近他的筷子,只有在他拿到两只筷子时才能进餐。进餐毕,放下筷子继续思考。

3.2 伪代码

分析:放在圆桌上的筷子是临界资源,在一段时间内只允许一位哲学家的使用。为了实现对筷子的互斥使用,使用一个信号量表示一只筷子,由这五个信号量构成信号量数组:

semaphore chopstick[5]={1,1,1,1,1};

所有信号量均被初始化为1,则第i位哲学家的活动可描述为:

do{/*当哲学家饥饿时,总是先拿起左边的筷子,再拿起右边的筷子*/wait(chopstick[i]);//拿起左筷子

wait(chopstick[(i+1)%5]); //拿起右筷子

eat(); //进餐

/*当哲学家进餐完成后,总是先放下左边的筷子,再放下右边的筷子*/signal(chopstick[i]);//放下左筷子

signal(chopstick[i+1]%5); //放下右筷子

think(); //思考

}while(true);

但是在上述情况中,假如五位哲学家同时饥饿而各自拿起左边的筷子时,就会使五个信号量chopstick均为0;而当他们再试图去拿右边的筷子时,都将因无筷子可拿造成无限的等待,产生死锁。

因此,需要对上述算法进行改进,限制仅当哲学家左右的两只筷子都可用时,才允许他拿起筷子进餐。可以利用AND 型信号量机制实现,也可以利用信号量的保护机制实现。利用信号量的保护机制实现的思想是通过记录型信号量mutex对取左侧和右侧筷子的操作进行保护,使之成为一个原子操作,这样可以防止死锁的出现。利用AND型信号量机制可获得最简洁的解法。

①使用记录信号量实现:

semaphore mutex = 1; //这个过程需要判断两根筷子是否可用,并保护起来

semaphore chopstick[5]={1,1,1,1,1};void philosopher(inti)

{while(true)

{/*这个过程中可能只能由一个人在吃饭,效率低下,有五只筷子,其实是可以达到两个人同时吃饭*/think();//思考

wait(mutex); //保护信号量

wait(chopstick[(i+1)%5]); //请求右边的筷子

wait(chopstick[i]); //请求左边的筷子

signal(mutex); //释放保护信号量

eat();              //进餐

signal(chopstick[(i+1)%5]); //释放右手边的筷子

signal(chopstick[i]); //释放左手边的筷子

}

}

②使用AND型信号量实现:

semaphore chopstick[5]={1,1,1,1,1};do{

think();//思考

Swait(chopstick[(i+1)%5],chopstick[i]); //请求筷子

eat(); //进餐

Ssignal(chopstick[(i+1)%5],chopstick[i]); //释放筷子

}while(true);

3.3 完整代码

1 #include

2 #include

3 #include

4 #include

5 #include

6 #include

7 #include

8 #include

9 #include

10 #include

11 #include

12 #include

13

14

15 union semun16 {17 intval;18 struct semid_ds *buf;19 unsigned short *array;20 struct seminfo *__buf;21 };22

23 #define ERR_EXIT(m) \

24 do{ \25 perror(m); \26 exit(EXIT_FAILURE); \27 } while(0)28

29 //申请一个资源

30 int wait_1chop(int no,intsemid)31 {32 //资源减1

33 struct sembuf sb = {no,-1,0};34 intret;35 ret = semop(semid,&sb,1);36 if(ret < 0) {37 ERR_EXIT("semop");38 }39 returnret;40 }41

42 //释放一个资源

43 int free_1chop(int no,intsemid)44 {45 //资源加1

46 struct sembuf sb = {no,1,0};47 intret;48 ret = semop(semid,&sb,1);49 if(ret < 0) {50 ERR_EXIT("semop");51 }52 returnret;53 }54

55 //筷子是一个临界资源

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

57

58 //相当于P操作59 //第一个参数是筷子编号60 //第二个参数是信号量编号

61 void wait_for_2chop(int no,intsemid)62 {63 //哲学家左边的筷子编号和哲学家编号是一样的

64 int left =no;65 //右边的筷子

66 int right = (no + 1) % 5;67

68 //筷子值是两个69 //操作的是两个信号量,即两种资源都满足,才进行操作

70 struct sembuf buf[2] ={71 {left,-1,0},72 {right,-1,0}73 };74 //信号集中有5个信号量,只是对其中的资源sembuf进行操作

75 semop(semid,buf,2);76 }77

78 //相当于V操作 ,释放筷子

79 void free_2chop(int no,intsemid)80 {81 int left =no;82 int right = (no + 1) % 5;83 struct sembuf buf[2] ={84 {left,1,0},85 {right,1,0}86 };87 semop(semid,buf,2);88 }89

90

91 //哲学家要做的事

92 void philosophere(int no,intsemid)93 {94 srand(getpid());95 for(;;)96 {97 #if 1

98 //当两只筷子都可用的时候,哲学家才能进餐

99 printf("%d is thinking\n",no); //思考中

100 sleep(DELAY);101 printf("%d is hungry\n",no); //饥饿

102 wait_for_2chop(no,semid); //拿到两只筷子才能吃饭

103 printf("%d is eating\n",no); //进餐

104 sleep(DELAY);105 free_2chop(no,semid); //释放两只筷子

106 #else

107 //可能会造成死锁

108 int left =no;109 int right = (no + 1) % 5;110 printf("%d is thinking\n",no); //思考中

111 sleep(DELAY);112 printf("%d is hungry\n",no); //饥饿

113 wait_1chop(left,semid); //拿起左筷子(只要有一个资源就申请)

114 sleep(DELAY);115 wait_1chop(right,semid); //拿起右筷子

116 printf("%d is eating\n",no); //进餐

117 sleep(DELAY);118 free_1chop(left,semid); //释放左筷子

119 free_1chop(right,semid); //释放右筷子

120 #endif

121 }122 }123

124

125 int main(int argc,char *argv[])126 {127 intsemid;128 //创建信号量集,其中有5个信号量

129 semid = semget(IPC_PRIVATE,5,IPC_CREAT | 0666);130 if(semid < 0) {131 ERR_EXIT("semid");132 }133 union semun su;134 su.val = 1;135 inti;136 for(i = 0;i < 5; ++i) {137 //第二个参数也是索引

138 semctl(semid,i,SETVAL,su);139 }140 //创建4个子进程

141 int num = 0;142 pid_t pid;143 for(i = 1;i < 5;++i)144 {145 pid =fork();146 if(pid < 0)147 {148 ERR_EXIT("fork");149 }150 if(0 == pid) //子进程

151 {152 num =i;153 break;154 }155 }156 //哲学家要做的事情

157 philosophere(num,semid);158 return 0;159 }

3.4 运行结果

3.5 解释运行结果

一开始,五个哲学家都在思考,一段时间后,3号哲学家饥饿,申请两只筷子满足后可以开始进餐,此时2号、4号和1号哲学家也饿了,但由于2号、4号与3号哲学家相邻,因此,他们需要等待3号进餐完毕放下筷子后,才可以进餐。而此时1号哲学家是可以进餐的。接着,0号哲学家饥饿,但由于筷子还在1号哲学家上,因此需要等待。然后3号哲学家进餐完毕,开始思考,4号哲学家可以进餐。1号哲学家进餐完毕,开始思考,2号哲学家可以进餐。3号哲学家饥饿,4号哲学家进餐完毕,开始思考,0号哲学家可以进餐。等2号哲学家进餐完毕,开始思考,3号哲学家可以开始进餐……

注意到当相邻的哲学家需要等到左右的筷子都可以使用时才可以进餐,因此如果哲学家是五位时,最多能有两位不相邻哲学家可以同时就餐。

4 References

java 第六次实验_操作系统第六次实验报告——使用信号量解决哲学家进餐问题...相关推荐

  1. 16281053_杨瑷彤_操作系统第五次实验-文件系统

    16281053_杨瑷彤_操作系统第五次实验-文件系统 源代码链接:https://github.com/rdjyat/operating-system/tree/master/操作系统实验五 1.实 ...

  2. java监听数据库操作_第十六篇——JDBC操作数据库之监听器

    JavaWeb应用中,很多的地方都和session有关.因此session相关的事件监听器,在日常工作中非常有用. 有时候我们需要统计当前在线的人数和访问人数总数,此时就可以使用监听器技术来很简单的实 ...

  3. java编写文件系统的方法_操作系统课程设计模拟文件系统Java

    [实例简介] 一个操作系统课程设计,使用java语言模拟磁盘文件系统实现,实现了FAT算法 [实例截图] [核心代码] e692cc3b-c785-40f6-babe-2f9d5383f034 └── ...

  4. java程序设计(小时钟)流程图_数字电路课程设计--电子钟实验报告

    一:要求 ①要有时钟显示功能,能够实现时.分.秒的显示 ②要有整点报时功能 ③要有设置时间功能. 二:流程图 三:主要部分的实现方案 1)秒脉冲电路:利用集成电路555定时器与电阻和电容组成多谐振荡器 ...

  5. 可变分区存储管理实验报告总结_操作系统第5次实验报告:内存管理

    姓名:吴永锋 学号:201821121051 班级:计算1812 动态分区分配是根据进程的实际需要,动态的为之分配内存空间.而在实现可变分区分配时,将涉及到分区分配中 所用的数据结构.分区分配算法和分 ...

  6. 干涉法测微小量实验_干涉法测微小量实验报告(90-95分)

    一.目的要求 [由学生写,线上学习不用写] 1.利用干涉法测量平凸透镜的曲率半径. 2.观察了解牛顿环干涉的原理和现象. 3.学会使用读数显微镜. 4.用逐差法进行数据处理. 二.实验仪器 [由学生写 ...

  7. 单片机彩灯移动实验_单片机课程设计彩灯实验.doc

    单片机课程设计彩灯实验 彩灯控制器设计 1.项目要求及参数 1.1用指令语句实现对C51的控制,从而实现对彩灯变化的控制. 1.2用定时器控制彩灯变化,用语句查询方式实现程序设计. 1.3用定时器控制 ...

  8. 干涉法测微小量实验_干涉法测微小量实验教案

    干涉法测微小量实验 一.实验简介: 光的干涉现象表明了光的波动的性质,干涉现象在科学研究与计量技术中 有着广泛的应用. 在干涉现象中, 不论何种干涉, 相邻干涉条纹的光程差的改变 都等于相干光的波长, ...

  9. 太阳电池板特性实验_太阳能电池板室外特性实验提纲

    研究性实验 太阳能电池板室外特性 实验方式: 根据下列提纲,在室外通过实际测试,以定量和定性的形式,了解太阳能电池板室外特性. 课前查阅: 太阳能电池板的种类及简要工作原理: 光电器件的基本属性: 超 ...

最新文章

  1. bzoj1588[HNOI2002]营业额统计——双向链表
  2. Win7下安装一个装逼文本编辑器Atom + activate-power-mode插件
  3. MongoDB 4.0 事务实现解析
  4. .ajax显示加载动画,jQuery Ajax 加载数据时异步显示加载动画
  5. java预期_预期. java的
  6. 关于软件组织培训的几个值得提倡的建议
  7. ubuntu16.04 修改本机密码
  8. Git小乌龟(TortoiseGit)使用详情
  9. java math 三角函数_Java中的三角函数
  10. 华为手机像素密度排行_华为荣耀20怎么调整像素密度,如何提升屏显清晰度呢...
  11. 百度智能api接口汇总
  12. Scrapy爬虫框架之爬取校花网图片
  13. Rainmeter音频频谱插件分享
  14. 不想结婚要小孩了!怎么破?
  15. OpenSSL生成.key、.crt、.pfx证书(Windows下)
  16. Landscape-版图几何设计规则DRC
  17. Aws 认证的相关总结
  18. hmacsha256 java实现_java实现HMACSHA256(md5私钥key)加密签名
  19. 开源堡垒机JumpServer远程命令执行漏洞复现
  20. 在TensorFlow中使用深度学习GANs处理图像

热门文章

  1. 记参加哈工大SCIR(赛尔)实验室笔试
  2. js 对象的键名 可以是数字么
  3. Linux文件查看命令
  4. 摄像头实时视频网页播放
  5. Unity游戏开发客户端面经——数学(初级)
  6. Spark SQL编程之RDD-RDD转换
  7. java获取当前时间前12个月内的年月信息
  8. mdin偏移_dif_input.c 源代码在线查看 - C8051F系列单片机开发与C语言编程 非常好的东西 资源下载 虫虫电子下载站...
  9. LIRO:紧耦合激光-惯性-测距里程计
  10. Android各个版本特性简介