山大操作系统实验五_第1页
山大操作系统实验五_第2页
山大操作系统实验五_第3页
已阅读5页,还剩11页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、大学软件学院操作系统实验报告实验题目 : 进程互斥实验实验目的 :进一步研究和实践操作系统中关于并发进程同步与互斥操作的一些经典问题的解 法, 加深对于非对称性互斥问题有关概念的理解 。观察和体验非对称性互斥问题的并 发控制方法。进一步了解Linux系统中IPC进程同步工具的用法,训练解决对该类问题 的实际编程 、 调试和分析问题的能力 。实验要求 :理发店问题 :假设理发店的理发室中有 3个理发椅子和 3个理发师 , 有一个可容纳 4 个顾客坐等理发的沙发 。此外还有一间等候室 , 可容纳 13位顾客等候进入理发室 。 顾 客如果发现理发店中顾客已满 超过 20人, 就不进入理发店 。在理发

2、店 , 理发师一旦有空就为坐在沙发上等待时间最长的顾客理发 , 同时空出的沙 发让在等候室中等待时间最长的的顾客就坐 。 顾客理完发后 , 可向任何一位理发师付 款。 但理发店只有一本现金登记册 , 在任一时刻只能记录一个顾客的付款 。 理发师在 没有顾客的时候就坐在理发椅子上睡眠 。 理发师的时间就用在理发 、收款、睡眠上 。请利用linux系统提供的IPC进程通信机制实验并实现理发店问题的一个解法。总结和分析例如实验和独立实验中观察到的调试和运行信息, 说明您对与解决非对称性互斥操作的算法有哪些新的理解和认识 ?为什么会出现进程饥饿现象 ?本实验 的饥饿现象是怎样表现的 ?怎样解决并发进程

3、间发生的饥饿现象?您对于并发进程间使用消息传递解决进程通信问题有哪些新的理解和认识 ?根据实验程序 、调试过程和 结果分析写出实验报告 。硬件环境 :CPU:P4/1.8MHZ 存:256MB 硬盘:10GB软件环境 :Ubuntu08.4 Linux 操作系统 Gnome 桌面 BASH_VERSION='3.2.33(1)-releasegcc version vi gedit OpenOffice 2.3实验步骤 :1. 问题分析假设理发店的理发室中有 3个理发椅子和 3个理发师 ,有一个可容纳 4个顾客坐等理 发的沙发 。此外还有一间等候室 ,可容纳 13位顾客等候进入理发室

4、。顾客如果发现理 发店中顾客已满 (超过 20人), 就不进入理发店 。在理发店 , 理发师一旦有空就为坐在沙发上等待时间最长的顾客理发,同时空出的沙发让在等候室中等待时间最长的的顾客就坐 。顾客理完发后 ,可向任何一位理发 师付款 。 但理发店只有一本现金登记册 , 在任一时刻只能记录一个顾客的付款 。理发 师在没有顾客的时候就坐在理发椅子上睡眠 。理发师的时间就用在理发 、收款 、睡眠 上。2. 算法设计说明该解法利用消息队列的每条消息代表每个顾客 , 将进入等候室的顾客组织到一个 队列 ,将坐入沙发的顾客组织到另一个队列 。理发师从沙发队列请出顾客 ,空出的沙 发位置再从等候室请入顾客进

5、入沙发队列 。三个理发师进程使用相同的程序段上下 文, 所有顾客使用同一个程序段上下文 。这样可防止产生太多进程 ,以便节省系统资 源。int sem_p(int semid, int index, int ipc_nowait) /P操作struct sembuf buf = 0, -1, 0;buf.sem_num = index;buf.sem_flg = ipc_nowait ? IPC_NOWAIT : 0;if(semop(semid, &buf, 1) = -1) if(ipc_nowait && errno = EAGAIN) return -2;els

6、eperror("a wrong operation to semaphore occured!"); return -1;return 0;int sem_v(int semid, int index, int ipc_nowait) /V操作struct sembuf buf = 0, 1, 0; buf.sem_num = index;buf.sem_flg = ipc_nowait ? IPC_NOWAIT : 0; if(semop(semid, &buf, 1) = -1) if(ipc_nowait && errno = EAGAIN)

7、 return -2;elseperror("a wrong operation to semaphore occured!"); return -1;return 0;Costumo:if(pid = fork() < 0) perror("fork error!");exit(EXIT_FAILURE);else if(pid = 0) /child processwhile(1) sem_p(wait_lock_semid, 1, 0); / 等待沙发上有人 sem_p(wait_semid, 0, 0); / 等待理发师有空 if(msg_

8、get(wait_msg, &msg, WAIT_ID_SOFA, 0) < 0) perror("message get error!");exit(-1);msg_send(wait_msg, WAIT_ID_CHAIR, msg.id, 0);printf("the consumer %d => chair, wait %d secondsn", msg.id,(time(NULL) - msg.timestamp);/sofa => chairsem_v(wait_semid, 1, 0); / 沙发上有空位了 sem_

9、v(wait_lock_semid, 0, 0); / 通知有人来理发了 return 0;if(pid = fork() < 0) perror("fork error!"); exit(EXIT_FAILURE);else if(pid = 0) /child processwhile(1) sem_p(wait_lock_semid, 2, 0); / 等待室有人 sem_p(wait_semid, 1, 0); / 沙发上有空位 if(msg_get(wait_msg, &msg, WAIT_ID_ROOM, 0) < 0) perror(&qu

10、ot;message get error!");exit(-1);msg_send(wait_msg, WAIT_ID_SOFA, msg.id, 0);printf("the consumer %d => sofa, wait %d secondsn", msg.id,(time(NULL) - msg.timestamp);/room => sofasem_v(wait_semid, 2, 0); / 等待室空出 1个位子 sem_v(wait_lock_semid, 1, 0); / 通知沙发上有人了 return 0;while(1)if(pi

11、d = fork()< 0) perror("fork error!"); exit(EXIT_FAILURE);else if(pid = 0) /检查理发店 (等, getpid(); /full进入等待室if(consumer_status = sem_p(wait_semid, 2, 1) = -2) / 待室 ) 是否已满printf(我是顾客%d ,理发店满了,我走人了。n else if(consumer_status = 0) / 仍然有空间printf(我是顾客%d,进入理发店n", getpid(); printf(" 我是顾客

12、 %d, 正在等待室等待 n", getpid(); msg_send(wait_msg, WAIT_ID_ROOM, getpid(), 0); / sem_v(wait_lock_semid, 2, 0); / 通知等待室有人了 exit(0);sleep(3); /Baker : if(pid2 = 0) while(1) if(barber_status = 0) if(sem_p(wait_lock_semid, 0, 1) = -2) /等待有人来理发或需要收银printf(" 我是 %d 号理发师 ,正在睡觉 。 zzzZZZn", barber_i

13、d); sem_p(wait_lock_semid, 0, 0);if(sem_p(wait_lock_semid, 3, 1) = 0) /如果是需要收银barber_status = 2;if(msg_get(wait_msg, &msg, WAIT_ID_CASH, 1) < 0) perror("message1 get error!");exit(-1);barber_consumer = msg.id;elsebarber_status = 1;if(msg_get(wait_msg, &msg, WAIT_ID_CHAIR, 1) <

14、; 0) perror("message2 get error!");exit(-1);barber_consumer = msg.id;else if(barber_status = 1) printf(" 我是 %d 号理发师 , 正在为 %d 进行理发 。 n", barber_id, barber_consumer);sleep(15);barber_status = 0;sem_v(wait_lock_semid, 3, 0); / 需要收银msg_send(wait_msg, WAIT_ID_CASH, barber_consumer, 0)

15、; sem_v(wait_lock_semid, 0, 0);elsesem_p(cash_semid, 0, 0); / 收银本的互斥锁printf(" 我是 %d 号理发师 , 正在为 %d 进行收银 。 n", barber_id, barber_consumer);sem_v(cash_semid, 0, 0);barber_status = 0;sem_vwait_semid, 0, 0; / 通知理发师有空了 else signalSIGINT, handler_exit; wait;3. 某种方法的伪代码理发师程序 Barber 建立一个互斥帐本信号量:s_a

16、ccount,初值=1;建立一个同步顾客信号量 : s_customer, 初值=0; 建立沙发消息队列 : q_sofa;建立等候室消息队列 : q_wait; 建立 3个理发师进程 : b1_pid, b2_pid, b3_pid; 每个理发师进程作 : while1 以阻塞方式从沙发队列接收一条消息 , 如果有消息 , 那么消息出沙发队列 模拟一顾客理发 ; 唤醒顾客进程 让下一顾客坐入沙发 。 用进程休眠一个随机时间模拟理发过程 。 理完发 ,使用帐本信号量记账 。 互斥的获取账本 记账 唤醒用账本理发师者 否那么没有消息 沙发上无顾客 那么理发师进程在沙发队列上睡眠 ; 当沙发队列有

17、消息时被唤醒 有顾客坐入沙发 。 顾客程序 customer while1 取沙发队列消息数 查沙发上顾客数 ; 如果消息数小于 4沙发没座满 以非阻塞方式从等候室队列接收一条消息 查等候室有顾客否 , 如果有消息将接收到的消息发送到沙发队列 等候室顾客坐入沙发 ; 否那么发送一条消息到沙发队列 新来的顾客直接坐入沙发 ; 否那么沙发坐满 取等候室队列消息数 查等候室顾客数 ;如果消息数小于 13 发送一条消息到等候室队列 等候室没满 ,新顾客进等候室 ; 否那么在顾客同步信号量上睡眠 等候室满暂不接待新顾客 ; 用进程休眠一个随机时间模拟顾客到达的时间间隔 。4. 实验收获通过本次试验 ,使

18、我加深了对进程互斥概念的理解 ,体验到了共享存 、 信号灯数组 以及消息队列的功能 。根本已经掌握了如何用消息队列控制和堵塞进程, 实现对共享存的有序访问 。另外 , 是我加深了对理发师算法的理解 ,找到了它与读者写者问题的 共同之处 :1.进程间的互斥 2.理发师类似读者进程 ,顾客类似写者进程 。最后 ,通过不 断的调试 ,使我熟练了在 Linux 环境下编程的技巧 , 对进程的创立与控制更加熟悉 。附录 A :本实验全部程序源代码及注释IPC.H#ifndef CZW_IPC_H_INCLUDED#define CZW_IPC_H_INCLUDED#include<errno.h&

19、gt;#include<sys/types.h> #include<sys/sem.h>int sem_create(const char *pathname, int proj_id, int nsems, int init_value) key_t keyid;int semid, i;if(keyid = ftok(pathname, proj_id) = -1) perror("ftok error!");return -1;if(semid = semget(keyid, nsems, IPC_CREAT | 0666) < 0) p

20、error("semget error!");return -1;for(i = 0; i < nsems; i+) semctl(semid, i, SETVAL, init_value);return semid;int sem_delete(const char *pathname, int proj_id) key_t keyid;int semid, i;if(keyid = ftok(pathname, proj_id) = -1) perror("ftok error!");return -1; if(semid = semget(k

21、eyid, 0, 0666) < 0) perror("semget error!");return -1; if(semctl(semid, 0, IPC_RMID) < 0) perror("sem delete fail!"); return -1;return 1;int sem_set(int semid, int index, int value) if(index = -1) /todo setallelseif(semctl(semid, index, SETVAL, value) < 0) perror("s

22、em set error!");return -1;return 0;int sem_p(int semid, int index, int ipc_nowait) /P操作struct sembuf buf = 0, -1, 0;buf.sem_num = index;buf.sem_flg = ipc_nowait ? IPC_NOWAIT : 0; if(semop(semid, &buf, 1) = -1) if(ipc_nowait && errno = EAGAIN) return -2;elseperror("a wrong opera

23、tion to semaphore occured!"); return -1;return 0;int sem_v(int semid, int index, int ipc_nowait) /V操作struct sembuf buf = 0, 1, 0;buf.sem_num = index;buf.sem_flg = ipc_nowait ? IPC_NOWAIT : 0; if(semop(semid, &buf, 1) = -1) if(ipc_nowait && errno = EAGAIN) return -2;elseperror("

24、a wrong operation to semaphore occured!"); return -1;return 0;int sem_show(int semid, int index) return semctl(semid, index, GETVAL);void *smh_create(const char *pathname, int proj_id, size_t size) key_t keyid;int shmid;int flags = IPC_CREAT | 0666;if(keyid = ftok(pathname, proj_id) = -1) perro

25、r("ftok error!");return (char *)-1;if(shmid = shmget(keyid, size, flags) = -1) perror("shmget error!");return (char *)-1;return shmat(shmid, NULL, 0); int msg_create(const char *pathname, int proj_id) key_t keyid;int msgid;int flags = IPC_CREAT | 0666;if(keyid = ftok(pathname, pr

26、oj_id) = -1) perror("ftok error!");return -1;if(msgid = msgget(keyid, flags) = -1) perror("msgget error!");return -1;return msgid;int msg_delete(const char *pathname, int proj_id) key_t keyid;int msgid, i;if(keyid = ftok(pathname, proj_id) = -1) perror("ftok error!");re

27、turn -1;if(msgid = msgget(keyid, 0666) < 0) perror("msgget error!"); return -1;if(msgctl(msgid, IPC_RMID) < 0) perror("msg delete fail!"); return -1;return 1;#endif / CZW_IPC_H_INCLUDEDEX5_H#ifndef EX5_H_INCLUDED#define EX5_H_INCLUDED#include<signal.h>#include "i

28、pc.h"#define WAIT_ID_SOFA 1#define WAIT_ID_ROOM 2#define WAIT_ID_CHAIR 3#define WAIT_ID_CASH 4 struct ex5msgbuflong mtype;int id;time_t timestamp;int msg_send(int msgid, int msgtype, int id, int ipc_nowait) struct ex5msgbuf msg; msg.mtype = msgtype;msg.id = id; msg.timestamp = time(NULL);if(msg

29、snd(msgid, &msg, sizeof(struct ex5msgbuf) - 4, ipc_nowait ? IPC_NOWAIT : 0) < 0)if(ipc_nowait && errno = EAGAIN) return -2;elseperror("msg send error!");return -1; return 0;int msg_get(int msgid, struct ex5msgbuf *msg, long msgtype, int ipc_nowait) return msgrcv(msgid, msg,

30、sizeof(struct ex5msgbuf) - 4, msgtype, (ipc_nowait IPC_NOWAIT : 0);#endif / EX5_H_INCLUDEDBaker:#include<stdio.h> #include<stdlib.h> #include "ex5.h" const int debug = 0; void handler_exit(int signo) sem_delete(".", 10); sem_delete(".", 11); msg_delete("

31、;.", 31); sem_delete(".", 110); exit(0);int main() int wait_semid = sem_create(".", 10, 3, 0);int wait_lock_semid = sem_create(".", 11, 4, 0);int wait_msg = msg_create(".", 31);int cash_semid = sem_create(".", 110, 1, 1);debug && printf(

32、"twait_semid is %dn", wait_semid);debug && printf("twait_lock_semid is %dn", wait_lock_semid);debug && printf("twait_msg is %dn", wait_msg);debug && printf("tcash_semid is %dn", cash_semid); sem_set(wait_semid, 0, 3);sem_set(wait_semid,

33、 1, 4);sem_set(wait_semid, 2, 13);pid_t pid3 = 0;int i;int barber_id, barber_status, barber_consumer;struct ex5msgbuf msg;for(i = 0; i < 3; i+)if(pidi = fork() < 0) perror("fork error!"); exit(EXIT_FAILURE);else if(pidi = 0) barber_id = i + 1; barber_status = 0;debug && print

34、f("tI'm barber%d, my pid is %dn",barber_id,getpid(); break;if(pid2 = 0) while(1) if(barber_status = 0) if(sem_p(wait_lock_semid, 0, 1) = -2) /等待有人来理发或需要收银printf(" 我是 %d 号理发师 ,正在睡觉 。 zzzZZZn", barber_id); sem_p(wait_lock_semid, 0, 0);if(sem_p(wait_lock_semid, 3, 1) = 0) /如果是需要

35、收银barber_status = 2;if(msg_get(wait_msg, &msg, WAIT_ID_CASH, 1) < 0) perror("message1 get error!");exit(-1);barber_consumer = msg.id;elsebarber_status = 1;if(msg_get(wait_msg, &msg, WAIT_ID_CHAIR, 1) < 0) perror("message2 get error!");exit(-1);barber_consumer = msg.

36、id;else if(barber_status = 1) printf(" 我是 %d 号理发师 , 正在为 %d 进行理发 。 n", barber_id, barber_consumer);sleep(15);barber_status = 0;sem_v(wait_lock_semid, 3, 0); / 需要收银msg_send(wait_msg, WAIT_ID_CASH, barber_consumer, 0); sem_v(wait_lock_semid, 0, 0);elsesem_p(cash_semid, 0, 0); / 收银本的互斥锁printf(

37、" 我是 %d 号理发师 , 正在为 %d 进行收银 。 n", barber_id, barber_consumer);sem_v(cash_semid, 0, 0);barber_status = 0;sem_v(wait_semid, 0, 0); / 通知理发师有空了elsesignal(SIGINT, handler_exit);wait();return 0;Costomer#include<stdio.h> #include<stdlib.h>#include "ex5.h" const int debug = 0;

38、int main() int wait_semid = sem_create(".", 10, 0, 0);int wait_lock_semid = sem_create(".", 11, 0, 0);int wait_msg = msg_create(".", 31);debug && printf("twait_semid is %dn", wait_semid);debug && printf("twait_lock_semid is %dn", wait

39、_lock_semid); debug && printf("twait_msg is %dn", wait_msg);debug && printf("twait_semid_0 is %dn", sem_show(wait_semid, 0);pid_t pid = 0;struct ex5msgbuf msg;int i;int consumer_status;if(pid = fork() < 0) perror("fork error!"); exit(EXIT_FAILURE);else if(pid = 0) /child process while(1) sem_p(wait_lock_semid, 1, 0); / 等待沙发上有人 sem_p(wait_semid, 0, 0); / 等待理发师有空 if(msg_get(wait_msg, &msg, WAIT_ID_SOFA, 0) < 0)

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

最新文档

评论

0/150

提交评论