版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、进程同步实验 张咪 软件四班 一、实验目的 总结和分析示例实验和独立实验中观察到的调试和运行信息,说明您对与解决非对称性互斥操作的算法有哪些新的理解和认识? 为什么会出现进程饥饿现象?本实验的饥饿现象是怎样表现的?怎样解决并发进程间发生的饥饿现象?您对于并发进程间使用消息传递解决进程通信问题有哪些新的理解和认识?根据实验程序、调试过程和结果分析写出实验报告。 二、实验要求 理发店问题:假设理发店的理发室中有3个理发椅子和3个理发师,有一个可容纳4个顾客坐等理发的沙发。此外还有一间等候室,可容纳13位顾客等候进入理发室。顾客如果发现理发店中顾客已满(超过20人),就不进入理发店。 在理发店内,理
2、发师一旦有空就为坐在沙发上等待时间最长的顾客理发,同时空出的沙发让在等候室中等待时间最长的的顾客就坐。顾客理完发后,可向任何一位理发师付款。但理发店只有一本现金登记册,在任一时刻只能记录一个顾客的付款。理发师在没有顾客的时候就坐在理发椅子上睡眠。理发师的时间就用在理发、收款、睡眠上。 请利用linux系统提供的IPC进程通信机制实验并实现理发店问题的一个解法。 三、实验环境 实验环境均为Linux操作系统,开发工具为gcc和g+。 四、实验思路 约束: 1 设置一个count变量来对顾客进行计数,该变量将被多个顾客进程互斥地访问并修改,通过一个互斥信号量mutext来实现。 count>
3、20时,就不进入理发店。 7<count<20时,count+,顾客申请等候室,进入等候室等待,用一个room信号量控制。然后等待申请沙发,用一个sofa信号量控制。然后申请椅子。 3<count<7时,count+,顾客坐在沙发上等待,等待申请椅子。 count<3时,count+,顾客坐在椅子上等待理发。 2.只有在理发椅空闲时,顾客才能做到理发椅上等待理发师理发,否则顾客便必须等待;只有当理发椅上有顾客时,理发师才可以开始理发,否则他也必须等待。可通过信号量empty和full来控制。 3理发师为顾客理发时,顾客必须等待理发的完成,并在理发完成后理发师唤醒他
4、,使用一个信号量finish来控制; 4 顾客理完发后必须向理发师付费,并等理发师收费后顾客才能离开;而理发师则需等待顾客付费,并在收费后唤醒顾客以允许他离开,这可分别通过两个信号量payment和receipt来控制。 初值:计数 int count=0 信号量empty=3;full=0;room=13;sofa=4;finish=0;pay=0;receipt=0; mutex=1; 理发师进程 while(1) wait(full); /等待理发椅上有顾客 剪头发 signal(finish); /通知顾客理发完成 wait(pay); /等待顾客付费 wait(mutex); /在任
5、一时刻只能记录一个顾客的付款 收费 signal(mutex); signal(receipt); /通知顾客收费完毕 顾客进程 wait(mutex); /count既用于判断,也要修改,所以为临界资源,用mutex管理互斥 if(count>20) /顾客大于20人 signal(mutex); 离开理发店 else/顾客小于20人 count=count+1;/进入理发店 if(count>7) /count>7,说明理发椅和沙发上都有人,需要到等待室等待 signal(mutex); wait(room);/申请进入等待室 在等待室等 wait(sofa); /申请s
6、ignal(room);/释放等坐在沙发上等 wait(empty);/等待理发椅为空 申请到理发椅 signal(sofa); /释放沙发 else if(count>3)/说明理发椅上都有人,需要坐到沙发上等待 signal(mutexwait(sofa);/申请沙坐在沙发wait(empty);/等待理发椅申请到理signal(sofa);/释放沙发 else/count<3,可以坐到理发椅上等待 signal(mutex); wait(empty); /申请理发椅 坐在理发椅上等待理发 signal(full); /通知理发师开始理发 理发 wait(finish); /等
7、待理发完毕 付款 signal(payment); /通知理发师已付款 wait(receipt); /等待理发师收款 理发师收费完成,顾客离开理发椅 signal(empty); /释放理发椅 wait(mutex); /对count 临界资源操作,用mutex完成互斥 count=count-1; /离开理发店 signal(mutex); 七、调试及实验结果 1、创建makefile文件 hdrs = ipc.h opts = -g -c c_src = cons.c ipc.c c_obj = cons.o ipc.o p_src = bar.c ipc.c p_obj = bar.o
8、 ipc.o all: producer consumer consumer: $(c_obj) gcc $(c_obj) -o consumer cons.o: $(c_src) $(hdrs) gcc $(opts) $(c_src) producer: $(p_obj) gcc $(p_obj) -o producer bar.o: $(p_src) $(hdrs) gcc $(opts) $(p_src) clean: rm cons bar *.o 2.执行make命令,结果出现了许多由于粗心造成的编译错误 3、修改程序后编译成功,打开两个终端,先运行producer.c,再运行co
9、nsumer.c 4、若按ctrl+c停止producer进程,则出现如下图结果。沙发坐满后顾客将进入等候室等待 5、若再次执行producer进程,将陆续唤醒在等待的顾客,结果如下图 6、若再停止producer,让等待室的人也满,则顾客会离开理发店,结果如下图 七、心得与收获 1、本次试验,使我基本掌握了怎样用消息队列控制和堵塞进程,实现对共享内存的有序访问。 2、msgrcv/msgsnd为linux系统中异步或进程间通信的一种机制,msgrcv()可以从消息队列中读取消息,msgsnd()将一个新的消息写入队列。 int msgsnd(int msqid, const void *ms
10、gp, size_t msgsz, int msgflg); ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg); msgflg:这个参数依然是是控制函数行为的标志,取值可以是:0,表示忽略;IPC_NOWAIT,如果消息队列为空,则返回一个ENOMSG,并将控制权交回调用函数的进程。 3、不仅加深了对进程互斥的理解,还使我加深了对理发师算法的理解,找到了它与读者写者问题的共同之处:(1).进程间的互斥(2).理发师类似读者进程,顾客类似写者进程。 4、编写程序时要细心,对于编译过程中出现的错
11、误,要有耐心去解决。 八、源代码 Ipc.h: #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/shm.h> #include <sys/sem.h> #include <sys/msg.h> #define BUFSZ 256 #define MAXVAL 100 #define STRSIZ 8 #define WRITERQUEST 1 #define READ
12、ERQUEST 2 #define FINISHED 3 /写请求标识 /读请求标识 /读写完成标识 typedef union semuns int val; Sem_uns; typedef struct msgbuf long mtype; int mid; Msg_buf; /信号量 key_t costomer_key; int costomer_sem; key_t account_key; int account_sem; int sem_val; int sem_flg; /消息队列 int wait_quest_flg; key_t wait_quest_key; int w
13、ait_quest_id; int wait_respond_flg; key_t wait_respond_key; int wait_respond_id; int sofa_quest_flg; key_t sofa_quest_key; int sofa_quest_id; int sofa_respond_flg; key_t sofa_respond_key; int sofa_respond_id; int get_ipc_id(char *proc_file,key_t key); char *set_shm(key_t shm_key,int shm_num,int shm_
14、flag); int set_msq(key_t msq_key,int msq_flag); int set_sem(key_t sem_key,int sem_val,int sem_flag); int down(int sem_id); int up(int sem_id); Ipc.c: #include ipc.h int get_ipc_id(char *proc_file,key_t key) FILE *pf; int i,j; char lineBUFSZ,columBUFSZ; if(pf = fopen(proc_file,r) = NULL) perror(Proc
15、file not open); exit(EXIT_FAILURE); fgets(line, BUFSZ, pf); while(!feof(pf) i = j = 0; fgets(line, BUFSZ,pf); while(linei = ' ') i+; while(linei !=' ') columj+ = linei+; columj = '0' if(atoi(colum) != key) continue; j=0; while(linei = ' ') i+; while(linei !=' '
16、;) columj+ = linei+; columj = '0' i = atoi(colum); fclose(pf); return i; fclose(pf); return -1; int down(int sem_id) struct sembuf buf; buf.sem_op = -1; buf.sem_num = 0; buf.sem_flg = SEM_UNDO; if(semop(sem_id,&buf,1) <0) perror(down error ); exit(EXIT_FAILURE); return EXIT_SUCCESS; i
17、nt up(int sem_id) struct sembuf buf; buf.sem_op = 1; buf.sem_num = 0; buf.sem_flg = SEM_UNDO; if(semop(sem_id,&buf,1) <0) perror(up error ); exit(EXIT_FAILURE); return EXIT_SUCCESS; int set_sem(key_t sem_key,int sem_val,int sem_flg) int sem_id; Sem_uns sem_arg; /测试由 sem_key 标识的信号灯数组是否已经建立 if(
18、sem_id = get_ipc_id(/proc/sysvipc/sem,sem_key) < 0 ) /semget 新建一个信号灯,其标号返回到 sem_id if(sem_id = semget(sem_key,1,sem_flg) < 0) perror(semaphore create error); exit(EXIT_FAILURE); /设置信号灯的初值 sem_arg.val = sem_val; if(semctl(sem_id,0,SETVAL,sem_arg) <0) perror(semaphore set error); exit(EXIT_FA
19、ILURE); return sem_id; char * set_shm(key_t shm_key,int shm_num,int shm_flg) int i,shm_id; char * shm_buf; /测试由 shm_key 标识的共享内存区是否已经建立 if(shm_id = get_ipc_id(/proc/sysvipc/shm,shm_key) < 0 ) /shmget 新建 一个长度为 shm_num 字节的共享内存,其标号返回到 shm_id if(shm_id = shmget(shm_key,shm_num,shm_flg) <0) perror(s
20、hareMemory set error); exit(EXIT_FAILURE); /shmat 将由 shm_id 标识的共享内存附加给指针 shm_buf if(shm_buf = (char *)shmat(shm_id,0,0) < (char *)0) perror(get shareMemory error); exit(EXIT_FAILURE); for(i=0; i<shm_num; i+) shm_bufi = 0; /初始为 0 /shm_key 标识的共享内存区已经建立,将由 shm_id 标识的共享内存附加给指针 shm_buf if(shm_buf =
21、 (char *)shmat(shm_id,0,0) < (char *)0) perror(get shareMemory error); exit(EXIT_FAILURE); return shm_buf; int set_msq(key_t msq_key,int msq_flg) int msq_id; /测试由 msq_key 标识的消息队列是否已经建立 if(msq_id = get_ipc_id(/proc/sysvipc/msg,msq_key) < 0 ) /msgget 新建一个消息队列,其标号返回到 msq_id if(msq_id = msgget(msq
22、_key,msq_flg) < 0) perror(messageQueue set error); exit(EXIT_FAILURE); return msq_id; Bar.c: #include ipc.h int main(int argc,char *argv) / int i; int rate; Msg_buf msg_arg; /可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度 if(argv1 != NULL) rate = atoi(argv1); else rate = 3; /一个请求消息队列 wait_quest_flg = IPC_CREAT|
23、0644; wait_quest_key = 101; wait_quest_id = set_msq(wait_quest_key,wait_quest_flg); /一个响应消息队列 wait_respond_flg = IPC_CREAT| 0644; wait_respond_key = 102; wait_respond_id = set_msq(wait_respond_key,wait_respond_flg); /一个请求消息队列 sofa_quest_flg = IPC_CREAT| 0644; sofa_quest_key = 201; sofa_quest_id = se
24、t_msq(sofa_quest_key,sofa_quest_flg); /一个响应消息队列 sofa_respond_flg = IPC_CREAT| 0644; sofa_respond_key = 202; sofa_respond_id = set_msq(sofa_respond_key,sofa_respond_flg); /信号量使用的变量 costomer_key = 301;/顾客同步信号灯键值 account_key = 302;/账簿互斥信号灯键值 sem_flg = IPC_CREAT | 0644; /顾客同步信号灯初值设为0 sem_val = 0; /获取顾客同
25、步信号灯,引用标识存 costomer_sem costomer_sem = set_sem(costomer_key,sem_val,sem_flg); /账簿互斥信号灯初值设为 1 sem_val = 1; /获取消费者同步信号灯,引用标识存 cons_sem account_sem = set_sem(account_key,sem_val,sem_flg); int pid1, pid2; pid1=fork(); if(pid1=0) while(1) / wait_quest_flg=IPC_NOWAIT; printf(%d号理发师睡眠n, getpid(); wait_ques
26、t_flg=0; /*msgrcv()可以从消息队列中读取消息,msgsnd()将一个新的消息写入队列 msgtyp等于0 则返回队列的最早的一个消息。 msgtyp大于0,则返回其类型为mtype的第一个消息。 msgtyp小于0,则返回其类型小于或等于mtype参数的绝对值的最小的一个消息。*/ if(msgrcv(sofa_quest_id, &msg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) /读沙发请求队列 msgsnd(sofa_respond_id, &msg_arg,sizeof(msg_arg), 0);/
27、往沙发回应队列里写 printf(%d号理发师为%d号顾客理发n, getpid(), msg_arg.mid); sleep(rate); down(account_sem); printf(%d号理发师收取%d号顾客交费n, getpid(), msg_arg.mid); up(account_sem); else pid2=fork(); if(pid2=0) while(1) / wait_quest_flg=IPC_NOWAIT; printf(%d号理发师睡眠n, getpid(); wait_quest_flg=0; if(msgrcv(sofa_quest_id, &m
28、sg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) msgsnd(sofa_respond_id, &msg_arg,sizeof(msg_arg), 0); printf(%d号理发师为%d号顾客理发n, getpid(), msg_arg.mid); sleep(rate); down(account_sem); printf(%d号理发师收取%d号顾客交费n, getpid(), msg_arg.mid); up(account_sem); else printf(%d号理发师睡眠n, getpid(); else while(1
29、) / wait_quest_flg=IPC_NOWAIT; printf(%d号理发师睡眠n, getpid(); wait_quest_flg=0; if(msgrcv(sofa_quest_id, &msg_arg, sizeof(msg_arg), 0, wait_quest_flg)>=0) msgsnd(sofa_respond_id, &msg_arg,sizeof(msg_arg), 0); printf(%d号理发师为%d号顾客理发n, getpid(), msg_arg.mid); sleep(rate); down(account_sem); pri
30、ntf(%d号理发师收取%d号顾客交费n, getpid(), msg_arg.mid); up(account_sem); else printf(%d号理发师睡眠n, getpid(); return 0; Cons.c: #include ipc.h int main(int argc,char *argv) int rate; Msg_buf msg_arg; /可在在命令行第一参数指定一个进程睡眠秒数,以调解进程执行速度 if(argv1 != NULL) rate = atoi(argv1); else rate = 3; /联系一个请求消息队列 wait_quest_flg =
31、IPC_CREAT| 0644; wait_quest_key = 101; wait_quest_id = set_msq(wait_quest_key,wait_quest_flg); /联系一个响应消息队列 wait_respond_flg = IPC_CREAT| 0644; wait_respond_key = 102; wait_respond_id = set_msq(wait_respond_key,wait_respond_flg); /联系一个请求消息队列 sofa_quest_flg = IPC_CREAT| 0644; sofa_quest_key = 201; sof
32、a_quest_id = set_msq(sofa_quest_key,sofa_quest_flg); /联系一个响应消息队列 sofa_respond_flg = IPC_CREAT| 0644; sofa_respond_key = 202; sofa_respond_id = set_msq(sofa_respond_key,sofa_respond_flg); /信号量使用的变量 costomer_key = 301;/顾客同步信号灯键值 account_key = 302;/账簿互斥信号灯键值 sem_flg = IPC_CREAT | 0644; /顾客同步信号灯初值设为0 sem_val = 0; /获取顾客同步信号灯,引用标识存 costomer_sem costomer_sem = set_sem(costomer_key,sem_val,sem_flg); /账簿互斥信号灯初值设为 1 sem_val = 1; /获取消费者同步信号灯,引用标识存 cons_sem account_sem = set_sem(account_key,sem_val,sem_flg); int sofa_count=0; int wait_count=0; int i=0; / int count=0; while(1) sleep(rate); / count+;
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 招标文件中的运输说明
- 增长的算法-空手
- 2024年九年级化学上册 第二单元 课题1 空气教案 (新版)新人教版
- 2024-2025学年高中数学 第一章 预备知识 4 一元二次函数与一元二次不等式 1.4.3 一元二次不等式的应用教案 北师大版必修第一册
- 2023六年级英语下册 Unit 8 What′s Your Dream第4课时教案 陕旅版(三起)
- 2024-2025学年新教材高中历史 第一单元 古代文明的产生与发展 第1课 文明的产生与早期发展教学教案 新人教版必修《中外历史纲要(下)》
- 八年级物理上册 4.2《探究汽化和液化的特点》教学设计 (新版)粤教沪版
- 2024-2025学年高中历史下学期第1周 新中国初期的外交教学设计
- 易制爆化学品库管员职责
- 钻井纠斜技术服务合同(2篇)
- 大一基础化学复习题
- 增值税专用发票清单模板
- 第一讲-视频拍摄入门(上)PPT优秀课件
- 办公室搬迁合同
- 北京电影学院ppt讲义.doc
- 乱世巨星谐音歌词.
- 部队保密工作心得体会最新三篇
- 硬笔书法练习米字格田字格(A4纸)word打印版
- 高温合金PPT课件
- 《药物过敏反应抢救流程》
- 毕业论文deform模拟坯料在旋转锻造中的应力变形
评论
0/150
提交评论