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

加入VIP,免费下载
 

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

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

下载须知

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

版权提示 | 免责声明

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

南昌大学操作系统实验报告材料二编程模拟进程间地同步和互斥Word文件下载.docx

1、sys/types.h/基本系统数据类型sys/wait.h/declarations for waitinglinux/sem.h/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;/建立一个文件指针 /等待信号

2、量的数值变为非负数,此处设为负值,相当于对信号量进行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_op:如果其值为正数,该值会加到现有的信号内含值中,通常用于释放所控资源的使用权;如果sem_op的值为负数,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于sem_op的绝对值,通常用于获取资源的使用权;如果sem_op的值为0,则操作将暂时阻塞,直到信号的值变为0。*/

3、 /写文件,写入的数值是当前进程的进程号 file=fopen(file_path,w); /写文件,若成功则返回文件起始地址;否则置0 if(file)/临界区 fprintf(file,%dn,number);/将进程号写入*file处 printf(将当前的进程号输到标准输出里。 fclose(file);/关闭文件 /发送信号,把信号量的数值加1,此处相当于对信号量进行V操作 sem_op.sem_op=1;/子进程写文件void do_child_loop(int sem_set_id,char *file_name) pid_t pid=getpid(); int i,j;/取得目

4、前进程的识别码,返回当前的进程的标识符 for(i=0;i3;i+) update_file(sem_set_id,file_name,pid); for(j=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

5、_id=-1)/若调用失败,输出错误类型,强制退出程序 perror(main: semget exit(1); /把第一个信号量的数值设置为1 sem_val.val=1; rc=semctl(sem_set_id,0,SETVAL,sem_val); if(rc=-1) /测试是否成功调用semclt()函数semctl /建立一些子进程,使它们可以同时以竞争的方式访问信号量NUM_PROCS; /通过fork()函数创建子进程 child_pid=fork(); switch(child_pid) case -1:fork case 0: /子进程写文件 do_child_loop(se

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

7、空时消耗数据。#include /系统读写安全相关函数fcntl.h/该头文件内包含了通过错误码来回报错误资讯的宏errno.h#define MAXSEM 5/声明三个信号灯IDint fullid;int emptyid;int mutxid;int main()/*在sembuf结构中,sem_num是相对应的信号量集中的某一个资源,所以其值是一个从0到相应的信号量集的资源总数(ipc_perm.sem_nsems)之间的整数。sem_op指明所要执行的操作,sem_flg说明函数semop的行为。sem_op的值是一个整数.释放相应的资源数,将sem_op的值加到信号量的值上. str

8、uct sembuf P,V; union semun arg;/声明共享主存 int *array; int *sum; int *set; int *get;/映射共享主存/*mmap是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存而系统会自动回写脏页面到对应的文件磁盘上即完成了对文件的操作而不必再调用read,write等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间从而可以实现不同进程间的文件共享。 array = (in

9、t *)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 , si

10、zeof( 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 ,

11、arg) = -1) perror(semctl setval error arg.val = MAXSEM; if(semctl(emptyid , 0 ,SETVAL , arg) = -1) perror( arg.val = 1; if(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

12、(fork() = 0 ) int i = 0; while( i 100)/semop(信号量,资源,数目) semop(emptyid , &P ,1 ); /mutex实现临界资源的互斥使用 semop(mutxid , &P , 1); array*(set)%MAXSEM = i + 1;Producer %dn, array(*set)%MAXSEM); /生产产品的标号+1 (*set)+;V , 1); semop(fullid , & i+; sleep(10);Producer is over exit(0); else /ConsumerA 进程 if(fork()=0)

13、 while(1)semop(fullid , &/判断是否所有产品都被消费了 if(*get = 100) break; *sum += array(*get)%MAXSEM;The ComsumerA Get Number %dn, array(*get)%MAXSEM ); (*get)+;/判断这次消费是否为最后一次消费 if( *get =100)The sum is %d n , *sum);V ,1 ); sleep(1);ConsumerA is over /Consumer B进程 if(*get = 100)The ComsumerB Get Number %dnConsu

14、merB is over / sleep(20);要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者和消费者的情形。思考:1、关于sleep()Sleep函数对于指定的时间间隔挂起当前的执行线程。 格式:VOID Sleep(DW

15、ORD dwMilliseconds ); dwMilliseconds:定义挂起执行线程的时间,以毫秒(ms)为单位。取值为0时,该线程将余下的时间片交给处于就绪状态的同一优先级的其他线程。若没有处于就绪状态的同一优先级的其他线程,则函数立即返回,该线程继续执行。若取值为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