操作系统实验报告生产者与消费者问题模拟.doc
操作系统上机实验报告实验名称:生产者与消费者问题模拟 实验目的:通过模拟生产者消费者问题理解进程或线程之间的同步与互斥。 实验内容:1、 设计一个环形缓冲区,大小为10,生产者依次向其中写入1到20,每个缓冲区中存放一个数字,消费者从中依次读取数字。 2、 相应的信号量;3、 生产者和消费者可按如下两种方式之一设计;(1) 设计成两个进程;(2) 设计成一个进程内的两个线程。4、 根据实验结果理解信号量的工作原理,进程或线程的同步互斥关系。实验步骤及分析:一管道(一)管道定义所谓管道,是指能够连接一个写进程和一个读进程的、并允许它们以生产者消费者方式进行通信的一个共享文件,又称为pipe文件。由写进程从管道的写入端(句柄1)将数据写入管道,而读进程则从管道的读出端(句柄0)读出数据。(二)所涉及的系统调用 1、pipe( )建立一无名管道。系统调用格式 pipe()参数定义int pipe();int 2;其中,1是写入端,0是读出端。该函数使用头文件如下:#include <unistd.h>#inlcude <signal.h>#include <stdio.h>2、read( )系统调用格式: read(fd,buf,nbyte)功能:从fd所指示的文件中读出nbyte个字节的数据,并将它们送至由指针buf所指示的缓冲区中。如该文件被加锁,等待,直到锁打开为止。参数定义: int read(fd,buf,nbyte); int fd; char *buf; unsigned nbyte;3、write( )系统调用格式 read(fd,buf,nbyte)功能:把nbyte 个字节的数据,从buf所指向的缓冲区写到由fd所指向的文件中。如文件加锁,暂停写入,直至开锁。参数定义同read( )。(三)参考程序#include <unistd.h>#include <signal.h>#include <stdio.h>int pid1,pid2; main( ) int fd2;char outpipe100,inpipe100;pipe(fd); /*创建一个管道*/while (pid1=fork( )=-1);if(pid1=0)lockf(fd1,1,0);/*把串放入数组outpipe中*/ sprintf(outpipe,"child 1 is using pipe!"); /*向管道写长为50字节的串*/ write(fd1,outpipe,50); sleep(5); /*自我阻塞5秒*/ lockf(fd1,0,0); exit(0); else while(pid2=fork( )=-1); if(pid2=0) lockf(fd1,1,0); /*互斥*/ sprintf(outpipe,"child 2 is using pipe!"); write(fd1,outpipe,50); sleep(5); lockf(fd1,0,0); exit(0); else wait(0); /*同步*/ read(fd0,inpipe,50);/*从管道中读长为50字节的串*/ printf("%sn",inpipe); wait(0); read(fd0,inpipe,50); printf("%sn",inpipe); exit(0); 编写过程:运行结果:二、信号机制(一)信号的基本概念每个信号都对应一个正整数常量(称为signal number,即信号编号。定义在系统头文件<signal.h>中),代表同一用户的诸进程之间传送事先约定的信息的类型,用于通知某进程发生了某异常事件。每个进程在运行时,都要通过信号机制来检查是否有信号到达。若有,便中断正在执行的程序,转向与该信号相对应的处理程序,以完成对该事件的处理;处理结束后再返回到原来的断点继续执行。实质上,信号机制是对中断机制的一种模拟,故在早期的UNIX版本中又把它称为软中断。(二)所涉及的中断调用1、kill( )系统调用格式int kill(pid,sig)参数定义int pid,sig;其中,pid是一个或一组进程的标识符,参数sig是要发送的软中断信号。(1)pid>0时,核心将信号发送给进程pid。(2)pid=0时,核心将信号发送给与发送进程同组的所有进程。(3)pid=-1时,核心将信号发送给所有用户标识符真正等于发送进程的有效用户标识号的进程。2、signal( )预置对信号的处理方式,允许调用进程控制软中断信号。系统调用格式signal(sig,function)头文件为 #include <signal.h>参数定义signal(sig,function)int sig;void (*func) ( ) function:在该进程中的一个函数地址,在核心返回用户态时,它以软中断信号的序号作为参数调用该函数,对除了信号SIGKILL,SIGTRAP和SIGPWR以外的信号,核心自动地重新设置软中断信号处理程序的值为SIG_DFL,一个进程不能捕获SIGKILL信号。(三)参考程序#include <stdio.h>#include <signal.h>#include <unistd.h>void waiting( ),stop( );int wait_mark;main( )int p1, p2; int stdout1;while(p1=fork( )=-1); /*创建子进程p1*/if (p1>0) while(p2=fork( )=-1); /*创建子进程p2*/if(p2>0) wait_mark=1;signal(SIGINT,stop); /*接收到c信号,转stop*/waiting( );kill(p1,16); /*向p1发软中断信号16*/kill(p2,17); /*向p2发软中断信号17*/wait(0); /*同步*/wait(0);printf("Parent process is killed!n");exit(0); else wait_mark=1;signal(17,stop); /*接收到软中断信号17,转stop*/waiting( );lockf(stdout1,1,0);printf("Child process 2 is killed by parent!n");lockf(stdout1,0,0);exit(0);elsewait_mark=1;signal(16,stop); /*接收到软中断信号16,转stop*/waiting( );lockf(stdout1,1,0);printf("Child process 1 is killed by parent!n");lockf(stdout1,0,0);exit(0);void waiting( )while(wait_mark!=0);void stop( )wait_mark=0;编译过程:运行结果:实验总结:在实验中很多粗心造成的问题,比如指令输错字母,代码写错字母,没有注意是否需要空格等。通过课堂的理论知识学习和实验课的上机实验,让我更能理解操作系统的知识。