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

上传人:1** 文档编号:359714 上传时间:2018-06-28 格式:DOCX 页数:11 大小:1.22MB
返回 下载 相关 举报
南昌大学操作系统实验报告二编程模拟进程间的同步和互斥_第1页
第1页 / 共11页
南昌大学操作系统实验报告二编程模拟进程间的同步和互斥_第2页
第2页 / 共11页
南昌大学操作系统实验报告二编程模拟进程间的同步和互斥_第3页
第3页 / 共11页
点击查看更多>>
资源描述
1南 昌 大 学 实 验 报 告-( 2) 编 程 模 拟 进 程 间 的 同 步 和 互 斥学生姓名: 张皓然 学 号: 5501215001 专业班级: 本硕 151 实验类型: 验证 综合 设计 创新 实验日期: 2017.5.5 实验成绩: 一、实验目的通过实验加强对进程同步和互斥的理解,并掌握进程(线程)的创建和调用方法。学会使用信号量解决资源共享问题。学生可以自己选择在 Windows 或 Linux 系统下编写。二、实验内容(一)以下为 Linux 系统下参考程序,请编译、运行并观察程序的输出,并分析实验结果,写出实验报告。#include/标准输入输出头文件#include/standard library 标准库头文件 #include/POSIX 标准定义的 unix 类系统定义符号常量的头文件,包含了许多UNIX 系统服务的函数原型,例如 read 函数、write 函数和 getpid 函数。#include/time.h 是 C 标准库头文件,主要是一些和时间相关的函数#include/基本系统数据类型#include/declarations for waiting#include/Semaphore operation flags#define NUM_PROCS 5/5 个子进程#define SEM_ID 250/信号量#define FILE_NAME /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_set_id,sem_op 是结构指针。sem_op:如果其值为正数,该值会加到现有的信号内含值中,通常用于释放所控资源的使用权;如果 sem_op 的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于 sem_op 的绝对值,通常用于获取资源的使用权;如果 sem_op 的值为 0,则操作将暂时阻塞,直到信号的值变为 0。*/写文件,写入的数值是当前进程的进程号file=fopen(file_path,w);/写文件,若成功则返回文件起始地址;否则置 02if(file)/临界区fprintf(file,%dn,number);/将进程号写入*file 处printf(%dn,number);将当前的进程号输到标准输出里。fclose(file);/关闭文件/发送信号,把信号量的数值加 1,此处相当于对信号量进行 V 操作sem_op.sem_num=0;sem_op.sem_op=1;sem_op.sem_flg=0;semop(sem_set_id,/子进程写文件void do_child_loop(int sem_set_id,char *file_name)pid_t pid=getpid();int i,j;/取得目前进程的识别码,返回当前的进程的标识符 for(i=0;i#include #include /系统读写安全相关函数#include #include #include /该头文件内包含了通过错误码来回报错误资讯的宏#include #include #define MAXSEM 5/声明三个信号灯 IDint fullid;int emptyid;5int mutxid;int main()/*在 sembuf 结构中, sem_num 是相对应的信号量集中的某一个资源,所以其值是一个从 0到相应的信号量集的资源总数(ipc_perm.sem_nsems )之间的整数。 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 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存而系统会自动回写脏页面到对应的文件磁盘上即完成了对文件的操作而不必再调用 read,write 等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间从而可以实现不同进程间的文件共享。*/array = (int *)mmap(NULL , sizeof( int )* MAXSEM,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);sum = (int *)mmap(NULL , sizeof( int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);get = (int *)mmap(NULL , sizeof( int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0);set = (int *)mmap(NULL , sizeof( int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); *sum = 0;*get = 0;*set = 0; /创建信号量、生成信号灯fullid= semget(IPC_PRIVATE,1,IPC_CREAT|00666); emptyid=semget(IPC_PRIVATE,1,IPC_CREAT|00666);mutxid=semget(IPC_PRIVATE,1,IPC_CREAT|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;6if(semctl(mutxid , 0 ,SETVAL , arg) = -1) perror(setctl setval error); /初始化 P,V 操作V.sem_num=0;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 , /mutex 实现临界资源的互斥使用semop(mutxid , array*(set)%MAXSEM = i + 1;printf(Producer %dn, array(*set)%MAXSEM);/生产产品的标号+1(*set)+;semop(mutxid , semop(fullid , i+; sleep(10);printf(Producer is over);exit(0);else /ConsumerA 进程if(fork()=0) while(1)semop(fullid , semop(mutxid , /判断是否所有产品都被消费了if(*get = 100) break;*sum += array(*get)%MAXSEM;printf(The ComsumerA Get Number %dn, array(*get)%MAXSEM );(*get)+;/判断这次消费是否为最后一次消费if( *get =100)7printf(The sum is %d n , *sum);semop(mutxid , semop(emptyid , sleep(1);printf(ConsumerA is over);exit(0);else /Consumer B 进程if(fork()=0) while(1)semop(fullid , semop(mutxid , if(*get = 100)break;*sum += array(*get)%MAXSEM;printf(The ComsumerB Get Number %dn, array(*get)%MAXSEM ); (*get)+;if( *get =100)printf(The sum is %d n , *sum);semop(mutxid , semop(emptyid , sleep(1);printf(ConsumerB is over);exit(0);/ sleep(20);return 0;89要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据) ,等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。思考:1、关于 sleep()Sleep 函数对于指定的时间间隔挂起当前的执行线程。 格式:VOID Sleep(DWORD dwMilliseconds ); dwMilliseconds:定义挂起执行线程的时间,以毫秒(ms)为单位。取值为 0 时,该线程将余下的时间片交给处于就绪状态的同一优先级的其他线程。若没有处于就绪状态的同一优先级的其他线程,则函数立即返回,该线程继续执行。若取值为INFINITE 则造成无限延迟。2.关于 semop在 Linux 下,PV 操作通过调用 semop 函数来实现。该函数定义在头文件 sys/sem.h中,原型如下:int semop(int semid,struct sembuf *sops,size_t nsops) ;流程图:10(三)第三个程序没有调试好11(四)心得体会程序的总体思路经过仔细分析还是比较清晰的。比如生产者消费者问题最主要的就是要实现两个条件判断,即缓冲区满的时候不允许生产者进行生产,若缓冲区空的话,则不进行消费者进行消费;在生产操作和消费操作之间进行相应的判断,正好符合 PV 信号量,先做 P 操作,若满足,则执行此进程,若不满足,则阻塞此进程,并做相应的 V 操作,即唤醒其对应的进程,从而很好的解决了生产者消费者问题。纸上得来终觉浅,绝知此事要躬行。
展开阅读全文
相关资源
相关搜索

当前位置:首页 > 图纸专区 > 大学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!