《2022年南昌大学操作系统实验报告二编程模拟进程间的同步和互斥.pdf》由会员分享,可在线阅读,更多相关《2022年南昌大学操作系统实验报告二编程模拟进程间的同步和互斥.pdf(11页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、南昌大学操作系统实验报告二编程模拟进程间的同步和互斥南昌大学实验报告-(2)编程 模 拟 进 程 间的 同 步 与 互 斥学生姓名 : 张皓然学号: 5501215001 专业班级 : 本硕 151 实验类型 : 验证 综合 设计 创新实验日期 : 2017、 5、5 实验成绩 : 一、实验目的通过实验加强对进程同步与互斥的理解,并掌握进程 (线程 )的创建与调用方法。 学会使用信号量解决资源共享问题。学生可以自己选择在Windows 或 Linux 系统下编写。二、实验内容(一)以下为 Linux系统下参考程序 ,请编译、运行并观察程序的输出,并分析实验结果 ,写出实验报告。#include
2、/标准输入输出头文件#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_I
3、D 250/信号量#define /tmp/sem_aaa #define DELAY 4000000 void update_ sem_set_id, char *, int number) struct sembuf sem_op; 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_op
4、:如果其值为正数,该值会加到现有的信号内含值中,通常用于释放所控资源的使用权;如果 sem_op 的值为负数 ,而其绝对值又大于信号的现值,操作将会阻塞,直到信号值大于或等于 sem_op 的绝对值 ,通常用于获取资源的使用权;如果 sem_op 的值为0,则操作将暂时阻塞,直到信号的值变为0。*/ /写文件 ,写入的数值就是当前进程的进程号(,w); /写文件 ,若成功则返回文件起始地址;否则置 0 if(file)/ 临界区精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 1 页,共 11 页 - -
5、- - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥fprintf(file,%dn,number);/将进程号写入*file 处printf(%dn,number); 将当前的进程号输到标准输出里。fclose(关闭文件 /发送信号 ,把信号量的数值加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 *) pid_t pid
6、=getpid(); int i,j;/ 取得目前进程的识别码,返回当前的进程的标识符for(i=0;i3;i+) update_); 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_
7、id=-1)/ 若调用失败 ,输出错误类型,强制退出程序perror(main: semget); exit(1); /把第一个信号量的数值设置为1 sem_val、 val=1; rc=semctl(sem_set_id,0,SETV AL,sem_val); if(rc=-1) / 测试就是否成功调用semclt()函数perror(main:semctl); exit(1); /建立一些子进程,使它们可以同时以竞争的方式访问信号量for(i=0;iNUM_PROCS;i+) /通过 fork() 函数创建子进程child_pid=fork(); 精品资料 - - - 欢迎下载 - - -
8、 - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 2 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥switch(child_pid) case -1: perror(fork); case 0: /子进程写文件do_child_loop(sem_set_id,); exit(0); default: /父进程接着运行break; /等待子进程结束for(i=0;iNUM_PROCS;i+) int child_status; wait(&child_status); printf(m
9、ain:were donen); fflush(stdout); return 0; 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 3 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥(二)生产者消费者问题生产者消费者问题描述了两个共享固定大小缓冲区的线程 即所谓的 “ 生产者 ” 与“ 消费者” 在实际运行时会发生的问题。生产者的主要作用就是生成一定量的数据放到缓冲区中,然后重复此过程。与此同时,消费者也在缓冲区消耗这些数据。该问题的关键就
10、就是要保证生产者不会在缓冲区满时加入数据,消费者也不会在缓冲区中空时消耗数据。#include #include #include /系统读写安全相关函数#include #include #include /该头文件内包含了通过错误码来回报错误资讯的宏#include #include #define MAXSEM 5 /声明三个信号灯ID int fullid; int emptyid; int mutxid; int main() Start 建立信号集并进行初始化操作就是否成功创建子进程先将进程 ID 写入某文件然后输出父进程继续运行,回收僵尸进程End 继续运行父进程并回收僵尸进程T
11、ure False False Ture 次数 =5 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 4 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥 /*在 sembuf 结构中 ,sem_num就是相对应的信号量集中的某一个资源,所以其值就是一个从0到相应的信号量集的资源总数(ipc_perm、sem_nsems)之间的整数。sem_op 指明所要执行的操作 ,sem_flg 说明函数semop 的行为。 sem_op 的值就是一个整数
12、、释放相应的资源数,将sem_op的值加到信号量的值上、*/ struct sembuf P,V; union semun arg; /声明共享主存int *array; int *sum; int *set; int *get; /映射共享主存/*mmap 就是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间实现文件磁盘地址与进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存而系统会自动回写脏页面到对应的文件磁盘上即完成了对文件的操作而不必再调用read,write 等系统调用函数。相反 ,内核空间对这段区域的修
13、改也直接反映用户空间从而可以实现不同进程间的文件共享。*/ 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_ANO
14、NYMOUS,-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_PRIV ATE,1,IPC_CREAT|00666); emptyid=semget(IPC_PRIV ATE,1,IPC_CREAT|00666); mutxid=semget(IPC_PRIV ATE,1,IPC_CREAT|00666); /为信号灯赋值arg
15、、val = 0; if(semctl(fullid , 0 , SETVAL , arg) = -1) perror(semctl setval error); arg、val = MAXSEM; if(semctl(emptyid , 0 ,SETV AL , arg) = -1) perror(semctl setval error); arg、val = 1; if(semctl(mutxid , 0 ,SETV AL , arg) = -1) perror(setctl setval error); 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载
16、 名师归纳 - - - - - - - - - -第 5 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥/初始化 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 , &P ,1 ); /mutex 实现临界资源的互斥使用s
17、emop(mutxid , &P , 1); array*(set)%MAXSEM = i + 1; printf(Producer %dn, array(*set)%MAXSEM); /生产产品的标号+1 (*set)+; semop(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); /
18、判断就是否所有产品都被消费了if(*get = 100) break; *sum += array(*get)%MAXSEM; printf(The ComsumerA 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 ); 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - -
19、 - - - - - -第 6 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥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; printf(The ComsumerB Get Number %dn, array(*
20、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; 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 7 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报
21、告二编程模拟进程间的同步和互斥精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 8 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥要解决该问题,就必须让生产者在缓冲区满时休眠(要么干脆就放弃数据),等到下次消费者消耗缓冲区中的数据的时候,生产者才能被唤醒,开始往缓冲区添加数据。同样 ,也可以让消费者在缓冲区空时进入休眠,等到生产者往缓冲区添加数据之后,再唤醒消费者。通常采用进程间通信的方法解决该问题,常用的方法有信号灯法等。如果解决方法不够完善
22、,则容易出现死锁的情况。出现死锁时,两个线程都会陷入休眠,等待对方唤醒自己。该问题也能被推广到多个生产者与消费者的情形。思考 : 1、关于 sleep() Sleep 函 数 对 于 指 定 的 时 间 间 隔 挂 起 当 前 的 执 行 线 程 。格 式 :VOID Sleep(DWORD dwMilliseconds ); dwMilliseconds: 定义挂起执行线程的时间,以毫秒 (ms)为单位。取值为0时,该线程将余下的时间片交给处于就绪状态的同一优先级的其她线程。若没有处于就绪状态的同一优先级的其她线程,则函数立即返回,该线程继续执行。若取值为INFINITE则造成无限延迟。2、
23、关于 semop 在 Linux 下,PV 操作通过调用semop函数来实现。该函数定义在头文件sys/sem、h中,原型如下 : int semop(int semid,struct sembuf *sops,size_t nsops); 流程图 : 精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 9 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥(三)第三个程序没有调试好(四)心得体会程序的总体思路经过仔细分析还就是比较清晰的。比如生产者
24、消费者问题最主要的就就是要实现两个条件判断,即缓冲区满的时候不允许生产者进行生产,若缓冲区空的话,则不进精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 10 页,共 11 页 - - - - - - - - - - 南昌大学操作系统实验报告二编程模拟进程间的同步和互斥行消费者进行消费;在生产操作与消费操作之间进行相应的判断,正好符合PV 信号量 ,先做 P操作 ,若满足 ,则执行此进程,若不满足 ,则阻塞此进程 ,并做相应的V 操作 ,即唤醒其对应的进程,从而很好的解决了生产者消费者问题。纸上得来终觉浅,绝知此事要躬行。精品资料 - - - 欢迎下载 - - - - - - - - - - - 欢迎下载 名师归纳 - - - - - - - - - -第 11 页,共 11 页 - - - - - - - - - -