实验五进程间通信实验一、实验目的1、了解什么是信号。
2、熟悉LINUX系统中进程之间软中断通信的基本原理。
3、了解什么是管道4、熟悉UNIX/LINUX支持的管道通信方式二、实验内容1、编写一段程序,使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到信号后,分别输出下列信息后终止:Child process 1 is killed by parent!Child process 2 is killed by parent!父进程等待两个子进程终止后,输出以下信息后终止:Parent process is killed!<参考程序>#include<stdio.h>#include<signal.h>#include<unistd.h>#include<sys/types.h>#include<sys/wait.h>int wait_mark;void waiting(),stop();void main(){int p1, p2;signal(SIGINT,stop);while((p1=fork())==-1);if(p1>0) /*在父进程中*/{while((p2=fork())==-1);If(p2>0) /*在父进程中*/{wait_mark=1;waiting(0);kill(p1,10);kill(p2,12);wait( );wait( );printf("parent process is killed!\n");exit(0);}else /*在子进程2中*/{wait_mark=1;signal(12,stop);waiting();lockf(1,1,0);printf("child process 2 is killed by parent!\n");lockf(1,0,0);exit(0);}}else /*在子进程1中*/{wait_mark=1;signal(10,stop);waiting();lockf(1,1,0);printf("child process 1 is killed by parent!\n");lockf(1,0,0);exit(0);}}void waiting(){while(wait_mark!=0);}void stop(){wait_mark=0;}实验要求:⑴运行程序并分析结果。
(2分)⑵该程序段前面部分用了两个wait(0),为什么?(1分)⑶该程序段中每个进程退出时都用了语句exit(0),为什么?(1分)答:(1)按下ctrl+c中断进程时,程序才执行,父进程打印消息,父进程kill子进程,子进程1收到消息上锁,然后解锁关闭进程,随后子进程2同样操作,然后父进程打印,最后中断进程。
(2)wait(0)暂时停止目前进程的执行,直到信号来到或子进程结束,如果在调用wait(0)时子进程已经结束,则wait(0)会立即返回子进程结束状态值。
(3)在强调处强行退出程序,运行一次程序就结束。
2、司机售票员问题编程用fork()创建一个子进程代表售票员,司机在父进程中,再用系统调用signal()让父进程(司机)捕捉来自子进程(售票员)发出的中断信号,让子进程(售票员)捕捉来自(司机)发出的中断信号,以实现进程间的同步运行。
(2分)#include <stdio.h>#include <sys/types.h>#include <signal.h>#include <unistd.h>int wait_mark;int pid2;void waiting(), stoping();void main() {int pid1;while ((pid1 = fork()) == -1);if (pid1 > 0) { //司机进程signal(SIGUSR2, stoping);while (1) {wait_mark = 1;sleep(1);printf("drive\n");printf("stop\n");kill(pid1,SIGUSR1); //发送信号给售票员进程; waiting(); //等待来自售票员的信号printf("start\n");printf("\n");}} else { //售票员进程signal(SIGUSR1, stoping);while (1) {wait_mark=1;waiting(); //等待来自司机的信号printf("open\n");printf("sale\n");printf("close\n");pid2 = getppid(); //得到司机进程识别码kill(pid2,SIGUSR2); //发送信号给司机进程}}}void waiting() {while (wait_mark != 0);}void stoping() {wait_mark = 0;}3、编制一段程序,实现进程的管道通信。
使用pipe()建立一条管道线。
两个子进程p1和p2分别向管道各写一句话:Child 1 is sending message!Child 2 is sending message!而父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。
<参考程序># include<unistd.h># include<signal.h># include<stdio.h>int pid1,pid2;main(){int fd[2];char OutPipe[100],InPipe[100];pipe(fd);while((pid1=fork())= = -1);if(pid1= =0){lockf(fd[1],1,0);sprintf(OutPipe,” child 1 process is sending message!”);write(fd[1],OutPipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{while((pid2=fork())= = -1);if(pid2= =0){lockf(fd[1],1,0);sprintf(OutPipe,” child 2 process is sending message!”);write(fd[1],OutPipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{wait(0);read(fd[0],InPipe,50);printf(“%s\n”,InPipe);wait(0);read(fd[0],InPipe,50);printf(“%s\n”,InPipe);exit(0);}}}实验要求:运行程序并分析结果。
(1分)答:先使用系统调用fork( )创建两个子进程,再用系统调用signal( )让父进程捕捉键盘上来的中断信号(即按ctrl+c键),当捕捉到中断信号后,父进程用系统调用kill( )向两个子进程发出信号,子进程捕捉到父进程发来的信号后,分别输出下列信息后终止。
4.在父进程中用pipe()建立一条管道线,往管道里写一句话,两个子进程接收这句话。
(2分)# include<unistd.h># include<signal.h># include<stdio.h># include<stdlib.h>#include<sys/wait.h>int pid1,pid2;int main(){int fd[2];char OutPipe[100],InPipe[100];pipe(fd);lockf(fd[1],1,0);printf("parents is sending message!\n");sprintf(OutPipe,"this is pepo parents msg!\n");write(fd[1],OutPipe,50);lockf(fd[1],0,0);while((pid1=fork())== -1||(pid2=fork())== -1);if(pid1==0&&pid2==0){ lockf(fd[0],1,0);read(fd[0],InPipe,50);printf("child 1 process is sending message!\n");printf("child 2 process is sending message!\n");printf("the message is %s\n",InPipe);sleep(3);read(fd[0],InPipe,50);printf("the message is %s\n",InPipe);lockf(fd[0],0,0);exit(0);}}四、实验总结和体会(1分)本次实验过程中遇到了许多编译不能通过的情况,这种情况大部分是因为程序没有应该有的头文件和格式不规范导致的,然后通过实验也了解了信号是不能用于信息交换的,只能用于进程中断控制。
对于信号来源和发送也做了一定了解。
后面两题是关于管道通信,如果两个通信进程不是来自共同的父进程,那么就不能使用管道机制。