实验6 进程间通信一、实验目的:通过本实验了解和掌握进程间通讯的相关知识,(1)了解进程通信的基本原理。
(2)了解和熟悉管道通信,消息传送机制及共享存储机制。
二.实验内容1.进程的管道通信阅读下列程序,完成实验任务。
#include<unistd.h>#include<signal.h>#include<stdio.h>int pid1,pid2;main(){int fd[2];char outpipe[100],inpipe[100];pipe(fd); //将fd装入管道中while((pid1=fork())==-1); //如果进程没有创建成功,则一直循环if(pid1==0) //如果是子进程{lockf(fd[1],1,0);sprintf(outpipe,"chile 1 process a message!");//将字符串读入到oupipe中去write(fd[1],outpipe,50); //将outpipe写入到fd[1]中sleep(5); //睡眠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 a message!");write(fd[1],outpipe,50);sleep(5);lockf(fd[1],0,0);exit(0);}else{wait(0); //等待进程read(fd[0],inpipe,50); //将inpipe读入fd[0]中去,printf("%s\n",inpipe); //打印出子进程2wait(0);read(fd[0],inpipe,50);printf("%s\n",inpipe); //打印出子进程1exit(0);}}}实验任务:(1),读懂上面的程序,编译执行,分析为什么会出现这样的结果。
答:分别将子进程1,2写入fd[1]中去,然后在fd[0]中打印出来。
(2),解释程序中sleep(5)语句的作用。
答:主要是起休眠作用。
如果去掉的话,两条语句一下子就打印到屏幕上,没法体现管道传送的过程。
实验截图如上。
2.共享存储区的创建,附接合断接。
使用系统调用shmget(),shmat(),shmdt()合shmct1(),编制一个长度为1kb的消息发送和接收程序。
源代码如下。
#include<sys/types.h>#include<sys/shm.h>#include<sys/ipc.h>#include<errno.h>#include<unistd.h>#include<stdio.h>#include<stdlib.h>#define SHMKEY 75int shmid,i;int *addr;int p1,p2;CLIENT() //客户端{int i;shmid =shmget(SHMKEY,1024,0777); //创建一个共享区SHMKEY为共享区区的名字,1024字节,0777为设置的标志。
addr = shmat(shmid,NULL,0); //shmat 共享存储区的附接。
将一个共享区附接到一个虚拟的地址空间上。
Shmid为连接共享区的标志,addr连接地址(区间),0表示返回的地址。
for(i = 10;i>=1;i--){while(*addr!=-1); //如果没有连接好地址,则一直循环printf("(client)sent:%d\n",i); //如果连接成功,输入i的值*addr = i; //将i的值赋给连接的地址}exit(0);}SERVER() //服务器{shmid = shmget(SHMKEY,1024,0777|IPC_CREAT);addr=(int*)shmat(shmid,NULL,0);do{*addr = -1;while(*addr == -1);printf("(server)received:%d\n",(*addr));//输出连接好的地址信息}while(*addr);shmctl(shmid,IPC_RMID,0);exit(0);}main(){p1 = fork();if(p1)SERVER();system("ipcs -m");p2=fork();if(p2)CLIENT();}实验任务:分析程序运行机制和过程,写出并分析程序运行结果。
实验截图如上。
3.消息的创建、发送和接收。
实验任务:使用系统调用msgget()、msgsnd()、msgrcv()及msgct1()编写一个内容与2(共享存储区,如上)功能相同的程序,并分析程序运行结果。
#include<stdio.h>#include<unistd.h>#include<stdlib.h>#include<sys/types.h>#include<sys/msg.h>#include<sys/ipc.h>#include<sys/wait.h>#include<string.h>#define MSGKEY 75struct msgform{long mtype;char mtext[1030];}msg;int msgqid,i;void CLIENT(){msgqid = msgget(MSGKEY,0777);msg.mtype = 1;strcpy (msg.mtext,"hello,world\n");printf("(client)sent\n");msgsnd(msgqid,&msg,1024,0);}void SERVER(){msgqid = msgget(MSGKEY,0777|IPC_CREAT);msgrcv(msgqid,&msg,1030,1,0);printf("(server)receiver:%s\n",msg.mtext);msgctl(msgqid,IPC_RMID,0);}main(){system("ipcs -q");if(fork())SERVER();else CLIENT();wait(0);wait(0);}四、信号机制实验任务:在Linux 下编程,主进程用fork()创建两个子进程,主进程重复显示一首歌词,期间当程序收到窗口传来的kill命令信号时(如使用Ctrl + C传进来的中断信号),显示“我是机器不止九条命!!!”然后继续显示歌词,并向两个子进程分别发送中断信号,子进程1受到中断信号后,显示“。
”,并结束运行,子进程2收到中断信号后,显示“。
”,并结束运行,主进程等待两个进程均结束后,输出“。
”,后终止运行。
#include <stdio.h>#include <stdlib.h>#include <signal.h>int p1,p2,i;void methodfunc(){printf("\n我是机器猫,我有九条命!\n");kill(p1,160);kill(p2,170);// exit(0);}void child1(){printf("\n我是大儿子,我生的伟大\n");exit(0);}void child2(){printf("\n我是小儿子,我死的光荣\n");exit(0);}main(){p1=fork();if(p1==0){while(1){sleep(1);signal(160,child1);signal(SIGINT,child1);}p2 = fork();}else{p2 = fork();if(p2==0){while(1){sleep(1);signal(170,child2);signal(SIGINT,child2);}}for(i=0;i<10;i++){sleep(1);printf("\n一个像秋天,一个像夏天\n");signal(SIGINT,methodfunc);}}printf("\n我是父亲,啊,伤心再见!!\n");}五、实验心得在此次试验中,感触最深的是还是子进程创建试验,虽然逻辑很简单,但是对fork ()函数不是很了解,导致试验做了很长时间,还有就是发送kill命令是,要子进程接收到,也是一个问题,通过长时间的测试,终于将试验中如何创建两个子进程,一个父进程,父进程首先接收到中断命令后,发送kill命令,然后子进程受到kill命令,作出反应,然后继续跳转到主进程中,等待程序结束,最终打印出“我是父亲,伤心啊,再见。
”程序便结束掉。