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

下载本文档

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

文档简介

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

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

3、试过程和结果分析写出实验报告。硬件环境: CPU: P4/1.8MHz 内存:256MB 硬盘: 10GB 软件环境: Ubuntu08.4Linux 操作系统 Gnome 桌面 2.18.3BASH_VERSION='3.2.33(1)-release gcc version 4.1.2 vi 3.1.2 gedit 2.18.2 OpenOffice 2.3实验步骤:1. 问题分析假设理发店的理发室中有3个理发椅子和3个理发师,有一个可容纳4个顾客坐等理发的沙发。此外还有一间等候室,可容纳13位顾客等候进入理发室。顾客如果发现理发店中顾客已满(超过20人),就不进入理发店。在理发店

4、内,理发师一旦有空就为坐在沙发上等待时间最长的顾客理发,同时空出的沙发让在等候室中等待时间最长的的顾客就坐。顾客理完发后,可向任何一位理发师付款。但理发店只有一本现金登记册,在任一时刻只能记录一个顾客的付款。理发师在没有顾客的时候就坐在理发椅子上睡眠。理发师的时间就用在理发、收款、睡眠上。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; else perror("a wrong operation to semaphore occured!");

6、 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; else perror("a wrong operation to semapho

7、re occured!"); return -1; return 0;Costumo: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) perro

8、r("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 => chair sem_v(wait_semid, 1, 0); /沙发上有空位了 sem_v(wait_lock_semid, 0, 0); /通知有人来理发了 return 0; if(

9、pid = fork() < 0) perror("fork error!"); exit(EXIT_FAILURE); else if(pid = 0) /child process while(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("message get error!"); exit(-1); msg_send

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

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

12、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_id); sem_p(wait_lock_semid, 0, 0); if

13、(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; else barber_status = 1; if(msg_get(wait_msg, &msg, WAIT_ID_CHAIR, 1) < 0) perror("message2 g

14、et 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); sem_v(wait_lock_semid, 0, 0);

15、 else sem_p(cash_semid, 0, 0); /收银本的互斥锁 printf("我是%d号理发师, 正在为%d进行收银。n", barber_id, barber_consumer); sem_v(cash_semid, 0, 0); barber_status = 0; sem_v(wait_semid, 0, 0); /通知理发师有空了 else signal(SIGINT, handler_exit); wait();3. 某种方法的伪代码理发师程序(Barber)建立一个互斥帐本信号量:s_account,初值=1;建立一个同步顾客信号量:s_cus

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

17、小于4(沙发没座满)以非阻塞方式从等候室队列接收一条消息(查等候室有顾客否),如果有消息将接收到的消息发送到沙发队列(等候室顾客坐入沙发);否则发送一条消息到沙发队列(新来的顾客直接坐入沙发);否则(沙发坐满)取等候室队列消息数(查等候室顾客数) ;如果消息数小于13发送一条消息到等候室队列(等候室没满,新顾客进等候室);否则在顾客同步信号量上睡眠(等候室满暂不接待新顾客);用进程休眠一个随机时间模拟顾客到达的时间间隔。4. 实验收获通过本次试验,使我加深了对进程互斥概念的理解,体验到了共享内存、信号灯数组以及消息队列的功能。基本已经掌握了如何用消息队列控制和堵塞进程,实现对共享内存的有序访问

18、。另外,是我加深了对理发师算法的理解,找到了它与读者写者问题的共同之处:1.进程间的互斥2.理发师类似读者进程,顾客类似写者进程。最后,通过不断的调试,使我熟练了在Linux环境下编程的技巧,对进程的创建与控制更加熟悉。附录 A: 本实验全部程序源代码及注释IPC.H#ifndef CZW_IPC_H_INCLUDED#define CZW_IPC_H_INCLUDED#include<errno.h>#include<sys/types.h>#include<sys/sem.h>int sem_create(const char *pathname, in

19、t 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) perror("semget error!"); return -1; for(i = 0; i < nsems; i+) semctl(semid, i,

20、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(keyid, 0, 0666) < 0) perror("semget error!"); return -1; if(semctl(semid,

21、 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 setall else if(semctl(semid, index, SETVAL, value) < 0) perror("sem set error!"); return -1; return 0;int sem_p(int semid, int index, int ipc

22、_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; else perror("a wrong operation to semaphore occured!"); return -1; return 0;int sem_v(int semid

23、, 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; else perror("a wrong operation to semaphore occured!"); return -1; return 0;

24、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) perror("ftok error!"); return (char *)-1; if(shmid = shmget

25、(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, proj_id) = -1) perror("ftok error!"); return -1; i

26、f(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!"); return -1; if(msgid = msgget(keyid, 0666) < 0) per

27、ror("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 "ipc.h"#define WAIT_ID_SOFA 1#define WAIT_ID_

28、ROOM 2#define WAIT_ID_CHAIR 3#define WAIT_ID_CASH 4struct ex5msgbuf long 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(msgsnd(msgid, &msg, sizeof(struct ex5msgbuf

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

30、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); sem_delete(".", 1

31、10); 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("twait_semid is %dn", wait_s

32、emid); 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, 1, 4); sem_set(wait_semid, 2, 13)

33、; 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 && printf("tI'm barber%d

34、, 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) /如果是需要收银 barber_status = 2; if(msg

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

36、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); else sem_p(cash_semid, 0, 0); /收银本的互斥锁 printf("我是%d号理发师, 正在为%d进

37、行收银。n", barber_id, barber_consumer); sem_v(cash_semid, 0, 0); barber_status = 0; sem_v(wait_semid, 0, 0); /通知理发师有空了 else signal(SIGINT, handler_exit); wait(); return 0;Costomer:#include<stdio.h>#include<stdlib.h>#include "ex5.h"const int debug = 0;int main() int wait_semid

38、 = 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_lock_semid); debug &

39、amp;& 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) perror(&

温馨提示

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

评论

0/150

提交评论