(操作系统原理和linux操作系统相结合的实验)实验二进程的通信一实验目的1 学会使用vi编辑器编辑C语言程序2 学会Linux环境下gcc的使用3 学会调试工具GDB的使用二实验原理1 利用linux提供的进程通信的系统调用设计进程通信程序,加深对进程通信概念的理解。
2 体会进程通信的方法和效果。
三实验环境PC机1台,Windows操作系统和其上的虚拟Linux操作系统。
四实验步骤1.管道通信(1)编写一个程序。
父进程创建一个子进程和一个无名管道fd,由子进程向管道写入信息“This is a message”,然后终止执行;父进程接收到子进程终止信号后从管道中读出并显示信息后结束。
#include<stdio.h>#include<unistd.h>main(){int p1,fd[2];char outpipe[50]; //定义读缓冲区char inpipe[50]="This is a message!"; //定义写缓冲区pipe(fd); //创建无名管道fdwhile((p1=fork())==-1);if (p1==0) //子进程返回{write(fd[1],inpipe,50); //写信息到管道exit(0);}else //父进程返回{wait(0); //等待子进程终止read(fd[0],outpipe,50); //从管道读信息到读缓冲区printf("%s\n",outpipe); //显示读到的信息exit(0);}}(2)父进程创建两个子进程,父子进程之间利用管道进行通信。
要求能显示父进程、子进程各自的信息,体现通信效果。
(源程序pipe_1.c)#include<stdio.h>main(){int I,r,j,k,l,p1,p2,fd[2];char buf[50],s[50];pipe(fd);while((p1=fork())==-1);if(p1==0){lockf(fd[1],1,0);sprintf(buf,"Child process p1 is sending message!\n");printf("Child process p1!\n");write(fd[1],buf,50);lockf(fd[1],0,0);sleep(5);j=getpid();k=getppid();printf("p1 %d is weakup.My parent process id is %d.\n",j,k);exit(0);}else{while((p2=fork())==-1);if(p2==0){lockf(fd[1],1,0);sprintf(buf,"Child process p2 is sending message!\n");printf("Child process p2!\n");write(fd[1],buf,50);lockf(fd[1],0,0);sleep(5);j=getpid();k=getppid();printf("p2 %d is weakup.My parent process id is %d.\n",j,k);exit(0);}else{I=getpid();wait(0);if(r=read(fd[0],s,50)==-1)printf("can’t read pip e.");elseprintf("Parent %d:%s\n",l,s);wait(0);if(r=read(fd[0],s,50)==-1)pr intf("can’t read pipe");elseprintf ( "Parent %d:%s\n",l,s);exit(0);}}}结果:2.共享内存通信。
编程实现消息的发送与接收:发送进程将要发送的消息从键盘输入,每输入一行就作为一条消息发送,用“end”作为结束消息。
(源代码:sndshm.c)接收进程从消息队列上逐个取出消息并显示输出,也用“end” 作为结束消息。
通过先运行发送进程然后再运行接收进程的方式来实现同步。
(源代码:rcvshm.c)发送进程源代码:sndshm.c如下:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<linux/shm.h>main(){int shmid; /*定义共享内存内部标识shmid */char *viraddr; /*定义附接共享内存的虚拟地址*/char buffer[BUFSIZ]; /*定义存放信息的字符型数组*/shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT); /*创建共享内存*/viraddr=(char*)shmat(shmid, 0,0); /*附接到进程的虚拟地址空间*/while(1) /*循环输入信息*/{puts("Enter some text:");fgets(buffer,BUFSIZ,stdin);strcat(viraddr,buffer); /*采用追加方式写到共享内存*/if(strncmp(buffer,"end",3)==0) /*输入为“end”时结束*/break;}shmdt(viraddr); /*断开附接*/exit(0);}接收进程源代码:rcvshm.c如下:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<linux/shm.h>main(){int shmid;char *viraddr;shmid=shmget(1234,BUFSIZ,0666|IPC_CREAT); /*获取共享内存*/viraddr=(char *)shmat(shmid,0,0); /*附接到进程的虚拟地址空间*/printf("Your message is :\n%s",viraddr); /*输出信息内容*/shmdt(viraddr); /*断开附接*/shmctl(shmid,IPC_RMID,0); /*撤消共享内存*/exit(0);}结果如下,由屏幕输出的结果看出,发送进程发送到共享内存中的信息已经被接收进程接收了。
3 消息缓冲通信。
发送进程将要发送的消息从键盘输入,每输入一行就作为一条消息发送,用“end”作为结束消息。
(源代码sndfile.c)接收进程从消息队列上逐个取出消息并显示输出,也用“end”作为结束消息。
设消息队列的key为1234。
(源代码rcvfile.c)源代码sndfile.c如下:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<linux/msg.h>#define MAXMSG 512 /*定义消息长度*/struct my_msg /*定义消息缓冲区数据结构*/{long int my_msg_type;char some_text[MAXMSG];}msg;main( ){int msgid; /*定义消息缓冲区内部标识*/char buffer[BUFSIZ]; /*定义用户缓冲区*/msgid=msgget(1234,0666|IPC_CREAT); /*创建消息队列,key为1234*/while(1){puts("Enter some text:"); /*提示键入消息内容*/fgets(buffer,BUFSIZ,stdin); /*标准输入送buffer*/msg.my_msg_type=1; /*设置消息类型为1*/strcpy(msg.some_text,buffer); /*buffer送消息缓冲*/msgsnd (msgid,&msg,MAXMSG,0); /*发送消息到消息队列*/if(strncmp(msg.some_text,"end",3)==0) /*消息为“end”则结束*/ break;}exit(0);}源代码rcvfile.c如下:#include<stdio.h>#include<stdlib.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<linux/msg.h>#define MAXMSG 512 /*定义消息长度*/struct my_msg /*定义消息f缓冲区数据结构*/{long int my_msg_type;char some_text[MAXMSG];}msg;main(){int msgid; /*定义消息缓冲区内部标识*/long int msg_to_receive=0;msgid=msgget(1234, 0666|IPC_CREAT); /*获取消息队列,key为1234*/ while (1){msgrcv (msgid, &msg, BUFSIZ, msg_to_receive, 0); /*接收消息*/printf ("You wrote:%s",msg.some_text); /*显示消息*/if (strncmp (msg.some_text,"end",3)==0) /*消息为“end”则结束*/ break;}msgctl (msgid, IPC_RMID,0); /*撤消消息队列*/ exit (0);}程序运行结果如下:。