您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > 操作系统实验(信号灯)
实验三进程间通信和信号灯班级:姓名:学号:1.理解Linux关于进程通信的概念。2.掌握通过无名管道PIPE进行进程间通信的方法。3.巩固进程同步概念和实现进程同步的方法。4.加深对生产者消费者问题的理解。5.学会使用Linux信号量控制系统调用(PV操作)。实验内容编写一个程序,该程序主进程用来接受用户键盘输入的信息,子进程则将键盘输入的内容显示在屏幕上,该过程要求重复出现,直到用户使用ctrl+c终止程序运行。该实验内容其实质也是生产者消费者的问题,即一个进程产生数据(由用户输入),另一个进程输出之前由用户输入的数据。两个进程之间通过进程通信(IPC)技术来实现消息的传递,为了简化编码的复杂度,我们使用Linux中的管道技术(无名PIPE)实现进程间通信(有兴趣的同学,可以在完成后尝试使用共享内存的方式来进行进程间通信)。我们要求使用PV操作对信号量进行控制,从而实现生产者进程和消费者进程之间合理有序的工作(进程同步问题的进一步深入理解)。这里的PV操作,我们利用Linux系统提供的信号量系统调用来实现。学习管道系统调用所需头文件:#includeunistd.hintpipe(intfiledes[2]);/*pipe()会建立管道,并将文件描述词由参数filedes数组返回。*/filedes[0]为管道里的读取端,所以pipe用read调用的filedes[1]则为管道的写入端。ssize_twrite(intfd,constvoid*buf,size_tcount);/*像fd所指向的管道操作符(文件)写入数据*/第一个参数表示所要写入数据的文件操作符,这里为管道操作符。第二个参数表示所要写入信息所在的缓存区。第三个参数表示缓冲区中前多少个数据应该被写入文件fd中。通常设定为缓冲区的大小。例子:write(filedes[1],buf,sizeof(buf);ssize_tread(intfd,constvoid*buf,size_tcount);/*读取fd所指向的管道操作符的数据到缓冲区buf中*/第一个参数表示所要读取数据的文件操作符,这里为管道操作符。第二个参数表示读取的数据存放在哪里(注意数据类型)。第三个参数表示读取读取多少个字符,一般为缓冲区的大小。例子:read(filedes[0],buf,sizeof(buf));请首先阅读下面程序,理解管道pipe如何使用,然后请输入该程序并编译运行,观察运行结果。我们希望子进程里的内容全部执行完毕,即先汇报自己是子进程和PID号,然后把信息写入管道,再报告信息写入完毕。然后父进程才开始执行,报告自己是父进程,并显示从子进程收到的信息,这时程序运行完毕。但由于进程推进的速度不可预知,所以该程序有问题。请思考如何利用信号灯控制(原语化),以达到预期的目的。(这里不要求重写此程序,因为后面的程序设计会涵盖该问题)学习信号量控制函数:所需头文件:#includesemaphore.h#includefcntl.h#includesys/stat.hsem_tvariable;/*定义一个信号量的指针*/例子:sem_t*mutex;sem_t*sem_open(constchar*name,intoflag);/*用来创建一个POSIX信号量或打开一个已经存POSIX在的信号量,返回值为该信号灯的指针*/第一个参数指明了型号量的外部名字,系统中的信号量是按信号量的名字进行识别的。第二个参数指明了对第一个参数所指定的型号量进行什么样的操作,一般使用O_CREAT表示创建一个信号量,当使用O_CREAT时,要求使用额外的参数指定该信号量的权限(类似于open函数的参数)。例子:mutex=sem_open(“mutex”,O_CREAT,0644,0);其中0644为权限位;0表示信号量初始值,该值可在后续初始化函数中做修改。sem_init(sem_t*sem,intpshared,unsignedintvalue);/*初始化信号量,在创建完信号量后使用*/第一个参数为之前定义的信号量指针。第二个参数表示该信号量是在线程间进行通信还是在进程间进行通信。当其值为0时,表示应用于线程间,当其值为1时,表示应用于进程间。第三个参数为一个非负整形变量,代表信号量的初始值(可用资源量)。例子:sem_init(mutex,1,1);sem_wait(sem_t*sem);/*申请资源,信号量值减一,P操作*/参数为要进行P操作的信号量的指针。例子:sem_wait(mutex);sem_post(sem_t*sem);/*释放资源,信号量值加一,V操作*/参数为要进行V操作的信号量的指针。例子:sem_post(mutex);程序编写请根据前面的知识写出一个程序,要求父进程提示用户输入字符串信息,用户输入完内容后,该内容会存入管道,然后子进程运行,从管道中读取父进程发来的信息,并打印在屏幕上。当子进程输出了管道中的信息后。父进程再次提示用户输入信息。程序不断重复,直到用户使用Ctrl+C终止程序的运行。运行效果应该如图所示:提示:父进程、子进程都应该有一个足够大小的字符数组用作保存输入和输出字符串的存储空间。对于字符串的输入可以使用gets()函数进行键盘输入内容的接受。对于信号量的PV操作控制的设计,可参考课本74页MODULE4.17进行程序设计。编译时要加入参数-pthread-lrt,以便链接系统编程库。如:gccsourcecode.c-pthread-lrt-omessenger你需要完成的内容:程序源码:#includeunistd.h#includefcntl.h#includesys/stat.h#includestdio.h#includestdlib.h#includesemaphore.h#includesys/types.hintmain(){intpid,fd[2];sem_t*mutex,*empty,*full;charserver_message[1024];charclient_message[1024];mutex=sem_open(mutex,O_CREAT,0644,0);empty=sem_open(empty,O_CREAT,0644,0);full=sem_open(full,O_CREAT,0644,0);sem_init(mutex,1,1);sem_init(empty,1,1);sem_init(full,1,0);pipe(fd);pid=fork();if(pid==0){while(1){sem_wait(full);sem_wait(mutex);printf(\n**********TheMessageReceivedfromtheFather*******\n);read(fd[0],client_message,1024);printf(%s,client_message);printf(\n**********MessageEnd*********\n);sem_post(mutex);sem_post(empty);}}else{while(1){sem_wait(empty);sem_wait(mutex);printf(\nPleasewriteamessagetotheChild.\n);gets(server_message);write(fd[1],server_message,1024);sem_post(mutex);sem_post(full);}}return0;}运行抓图:对程序的分析:首先创建了了3个信号量,用来控制进程有序的执行。子进程是消耗者在消耗时先对资源数信号灯和互斥信号灯执行p操作,消耗资源之后,对空缓存区数量信号灯和互斥信号灯执行v操作。父进程是生产者,在生产的时先对空缓存区数量信号灯和互斥信号灯执行p操作,生产完之后,对资源数信号灯和互斥信号灯进行v操作。3个信号灯很好的控制父子进程有序的生产和消费。
本文标题:操作系统实验(信号灯)
链接地址:https://www.777doc.com/doc-5754403 .html