ImageVerifierCode 换一换
格式:DOCX , 页数:16 ,大小:1.33MB ,
资源ID:2671175      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bingdoc.com/d-2671175.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(南昌大学操作系统实验报告二编程模拟进程间的同步和互斥.docx)为本站会员(b****1)主动上传,冰点文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰点文库(发送邮件至service@bingdoc.com或直接QQ联系客服),我们立即给予删除!

南昌大学操作系统实验报告二编程模拟进程间的同步和互斥.docx

1、南昌大学操作系统实验报告二编程模拟进程间的同步和互斥 南昌大学实验报告 -(2)编程模拟进程间的同步和互斥学生姓名: 张皓然 学 号: * 专业班级: 本硕151 实验类型: 验证 综合 设计 创新 实验日期: 2017。5.5 实验成绩: 一、实验目的通过实验加强对进程同步和互斥的理解,并掌握进程(线程)的创建和调用方法.学会使用信号量解决资源共享问题.学生可以自己选择在Windows或Linux系统下编写。二、实验内容(一)以下为Linux系统下参考程序,请编译、运行并观察程序的输出,并分析实验结果,写出实验报告.include/标准输入输出头文件#includestdlib。h/stan

2、dard library标准库头文件 includeunistd.h/POSIX标准定义的unix类系统定义符号常量的头文件,包含了许多UNIX系统服务的函数原型,例如read函数、write函数和getpid函数。#include/time。h是C标准库头文件,主要是一些和时间相关的函数#includesys/types。h/基本系统数据类型#include/declarations for waiting#include/Semaphore operation flagsdefine NUM_PROCS 5/5个子进程define SEM_ID 250/信号量#define FILE_NA

3、ME ”/tmp/sem_aaa#define DELAY 4000000void update_file(int sem_set_id, char *file_path, int number) struct sembuf sem_op; FILE *file;/建立一个文件指针 /等待信号量的数值变为非负数,此处设为负值,相当于对信号量进行P操作 sem_op.sem_num=0; sem_op。sem_op=1; sem_op.sem_flg=0; semop(sem_set_id,sem_op,1);/操作一组信号,进程的标识符号为sem_set_id,sem_op是结构指针。sem_

4、op:如果其值为正数,该值会加到现有的信号内含值中,通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值,通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。*/ /写文件,写入的数值是当前进程的进程号 file=fopen(file_path,w”); /写文件,若成功则返回文件起始地址;否则置0 if(file)/临界区 fprintf(file,”%dn,number);/将进程号写入file处 printf(”dn,number);将当前的进程号输到标准输出里。

5、 fclose(file);/关闭文件 /发送信号,把信号量的数值加1,此处相当于对信号量进行V操作 sem_op.sem_num=0; sem_op。sem_op=1; sem_op.sem_flg=0; semop(sem_set_id,sem_op,1);/子进程写文件void do_child_loop(int sem_set_id,char *file_name) pid_t pid=getpid(); int i,j;/取得目前进程的识别码,返回当前的进程的标识符 for(i=0;i3;i+) update_file(sem_set_id,file_name,pid); for(j

6、=0;j4000000;j+); int main(int argc,char *argv) int sem_set_id; /信号量集的ID union semun sem_val; /信号量的数值,用于semctl() int child_pid; int i; int rc; / 建立信号量集,ID是250,其中只有一个信号量 sem_set_id=semget(SEM_ID,1,IPC_CREAT|0600); if(sem_set_id=1)/若调用失败,输出错误类型,强制退出程序 perror(”main: semget); exit(1); /把第一个信号量的数值设置为1 sem

7、_val。val=1; rc=semctl(sem_set_id,0,SETVAL,sem_val); if(rc=-1) /测试是否成功调用semclt()函数 perror(”main:semctl); exit(1); /建立一些子进程,使它们可以同时以竞争的方式访问信号量 for(i=0;iNUM_PROCS;i+) /通过fork()函数创建子进程 child_pid=fork(); switch(child_pid) case 1: perror(fork); case 0: /子进程写文件 do_child_loop(sem_set_id,FILE_NAME); exit(0);

8、 default: /父进程接着运行 break; /等待子进程结束 for(i=0;iNUM_PROCS;i+) int child_status; wait(&child_status); printf(”main:were donen); fflush(stdout); return 0;(二)生产者消费者问题生产者消费者问题描述了两个共享固定大小缓冲区的线程即所谓的“生产者和“消费者”在实际运行时会发生的问题。生产者的主要作用是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区

9、中空时消耗数据。include include linux/sem。h/系统读写安全相关函数include fcntl。hinclude unistd。h#include stdio.h/该头文件内包含了通过错误码来回报错误资讯的宏include errno.h#include time.h#define MAXSEM 5/声明三个信号灯IDint fullid;int emptyid;int mutxid;int main()/在sembuf结构中,sem_num是相对应的信号量集中的某一个资源,所以其值是一个从0到相应的信号量集的资源总数(ipc_perm.sem_nsems)之间的整数。

10、sem_op指明所要执行的操作,sem_flg说明函数semop的行为。sem_op的值是一个整数。释放相应的资源数,将sem_op的值加到信号量的值上./ struct sembuf P,V; union semun arg;/声明共享主存 int array; int sum; int set; int *get;/映射共享主存/*mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存而系统会自动回写脏页面到对应的文件磁盘上即完成了对文件的

11、操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间从而可以实现不同进程间的文件共享.*/ array = (int )mmap(NULL , sizeof( int )* MAXSEM,PROT_READPROT_WRITE,MAP_SHAREDMAP_ANONYMOUS,1,0); sum = (int )mmap(NULL , sizeof( int),PROT_READPROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,1,0); get = (int )mmap(NULL , sizeof( int),PROT_RE

12、ADPROT_WRITE,MAP_SHAREDMAP_ANONYMOUS,1,0); set = (int )mmap(NULL , sizeof( int),PROT_READPROT_WRITE,MAP_SHAREDMAP_ANONYMOUS,1,0); sum = 0; get = 0; set = 0; /创建信号量、生成信号灯 fullid= semget(IPC_PRIVATE,1,IPC_CREAT00666); emptyid=semget(IPC_PRIVATE,1,IPC_CREAT00666); mutxid=semget(IPC_PRIVATE,1,IPC_CREAT|

13、00666); /为信号灯赋值 arg。val = 0; if(semctl(fullid , 0 , SETVAL , arg) = 1) perror(semctl setval error”); arg.val = MAXSEM; if(semctl(emptyid , 0 ,SETVAL , arg) = -1) perror(semctl setval error”); arg。val = 1; if(semctl(mutxid , 0 ,SETVAL , arg) = 1) perror(”setctl setval error”); /初始化P,V操作 V.sem_num=0;

14、V.sem_op =1; V.sem_flg=SEM_UNDO; P.sem_num=0; P。sem_op =-1; P.sem_flg=SEM_UNDO; /生产者进程 if(fork() = 0 ) int i = 0; while( i 100)/semop(信号量,资源,数目) semop(emptyid , P ,1 ); /mutex实现临界资源的互斥使用 semop(mutxid , P , 1); array*(set)MAXSEM = i + 1; printf(Producer dn, array(*set)%MAXSEM); /生产产品的标号+1 (set)+; sem

15、op(mutxid , V , 1); semop(fullid , &V , 1); i+; sleep(10); printf(Producer is over); exit(0); else /ConsumerA 进程 if(fork()=0) while(1)semop(fullid , P , 1); semop(mutxid , P , 1);/判断是否所有产品都被消费了 if(get = 100) break; sum += array(get)%MAXSEM; printf(”The ComsumerA Get Number dn, array(get)%MAXSEM ); (

16、get)+;/判断这次消费是否为最后一次消费 if( get =100) printf(The sum is d n , *sum); semop(mutxid , V , 1); semop(emptyid , &V ,1 ); sleep(1); printf(”ConsumerA is over); exit(0); else /Consumer B进程 if(fork()=0) while(1) semop(fullid , P , 1); semop(mutxid , P , 1); if(*get = 100) break; sum += array(get)MAXSEM; pri

17、ntf(”The ComsumerB Get Number dn”, array(get)MAXSEM ); (get)+; if( *get =100) printf(The sum is d n ”, sum); semop(mutxid , &V , 1); semop(emptyid , &V ,1 ); sleep(1); printf(ConsumerB is over); exit(0); / sleep(20); return 0;要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据.

18、同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。思考:1、关于sleep()Sleep函数对于指定的时间间隔挂起当前的执行线程。 格式:VOID Sleep(DWORD dwMilliseconds ); dwMilliseconds:定义挂起执行线程的时间,以毫秒(ms)为单位.取值为0时,该线程将余下的时间片交给处于就绪状态的同一优先级的其他线程。若没有

19、处于就绪状态的同一优先级的其他线程,则函数立即返回,该线程继续执行。若取值为INFINITE则造成无限延迟。2.关于semop在 Linux 下,PV 操作通过调用semop函数来实现。该函数定义在头文件 sys/sem。h中,原型如下:int semop(int semid,struct sembuf *sops,size_t nsops);流程图:(三)第三个程序没有调试好(四)心得体会程序的总体思路经过仔细分析还是比较清晰的.比如生产者消费者问题最主要的就是要实现两个条件判断,即缓冲区满的时候不允许生产者进行生产,若缓冲区空的话,则不进行消费者进行消费;在生产操作和消费操作之间进行相应的判断,正好符合PV信号量,先做P操作,若满足,则执行此进程,若不满足,则阻塞此进程,并做相应的V操作,即唤醒其对应的进程,从而很好的解决了生产者-消费者问题。纸上得来终觉浅,绝知此事要躬行。

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2