一、实验目的
1. 了解管道通信的特点,掌握管道通信的使用方法。
2. 了解消息队列通信机制及原理,掌握消息队列相关系统调用的使用方法及功能。
二、实验项目内容
管道通信:
1. 父进程创建管道和两个子进程p1和p2
2. 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数
据,写完关闭文件,然后向管道写入一条消息“ok”,目的是通知进程p2可以读取文件内容了。
3. 子进程p2通过管道读取消息,如果消息是“ok”,则打开文件,读取文件内容,并将其输出到屏幕上,关闭文件.消息队列:
1. 父进程创建管道和两个子进程p1和p2
2. 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向消息队列写入一条消息“ok”,目的是通知进程p2可以读取文件内容了
3. 子进程p2从消息队列读取消息,如果消息是“ok”,则打开文件,读取文件内容,并将其输出到屏幕上,关闭文件.
三、试验过程及算法
(一) 实验流程图
(二) 实验过程及算法
两个程序过程和算法相似,因为是比较两种不同的通信方式,大致过程如下:
- 父(主)进程创建管道和两个子进程p1和p2;
- 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向消息队列或管道写入一条消息“ok”,目的是通知进程p2可以读取文件内容了;
- 子进程p2从消息队列或管道读取消息,如果消息是“ok”,则打开文件,读取文件内容,并将其输出到屏幕上,关闭文件.
五、 实验结果以及分析:
(一) 实验结果
上两张图是管道通信程序运行前后文件夹内容,产生1.txt文件。
上两张图是管道通信程序和消息队列程序运行结果,进程2均成功接收到进程1的消息且读取到文件中进程1留存的消息:hello, childTwo, this childOne!。
上两张图是程序产生1.txt和2.txt文件并写入信息的截图。
(二) 分析
在最初的程序结果输出中,进程2的接收信息总是先输出,开始以为是程序错误,但看输出结果发现进程2顺利读取输出了文件中的信息。仔细想想,这是很正常的情况,进程p1和进程p2同时执行,但可能p1执行的时间片到了,p2接着执行了或者说p2抢占了输出设备,所以进程p2的结果先输出。
六 实验程序代码:
(一)管道通信程序源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
void childProcessfunc(int i,int w_fd,int r_fd){
switch(i){
FILE *pFile; //clear the file pointer
case 1:
close(r_fd); //close the read
printf("welcome in child process one:\n open the file of 1.txt...\n");
//open the file of 1.txt, program will create this file when it's not existed, otherwise rewrite it.
//fail to open the file
if(NULL == (pFile = fopen("1.txt", "w"))){
printf("error\n");
exit(1);
}
//write the string into 1.txt
fwrite("hello, childTwo, this is childOne!",1,strlen("hello, childTwo, this is childOne!"),pFile);
fclose(pFile); //close file
//send the signal by pipe
printf(" Sending the message to child process two...\n");
write(w_fd,"OK",strlen("OK"));
break;
case 2:
char readBuffer[80];
close(w_fd); //close the write
int nBytes=read(r_fd,readBuffer,sizeof(readBuffer));
printf("welcome in child process two:\n open the file of 2.txt...\n");
//when the message is "OK"
if(strcmp(readBuffer, "OK") == 0){
printf(" start read the file...\n the content of 1.txt is : \n ");
//fail to open the file
if(NULL == (pFile = fopen("1.txt", "r"))){
printf("error\n");
exit(1);
}
char ch;
//get a char once and output
while(EOF != (ch=fgetc(pFile))){
printf("%c", ch);
}
fclose(pFile); //close file
}
break;
}
exit(0);
}
int main(){
int fd[2];
pid_t childPidOne,childPidTwo;
pipe(fd);
int w_fd=fd[1]; //port of write
int r_fd=fd[0]; //port of read
//create two child process No.1 and No.2
for (int i = 1; i <= 2; i++){
pid_t child=fork();
//create process failed
if (child==-1)
{
printf("Error hanppened in fork function!\n");
return 0;
}
//exert function when success
else if(child==0)
{
childProcessfunc(i,w_fd,r_fd);
}
//parent wait for child process
pid_t tempPid=wait(NULL);
}
return 0;
}
(二) 消息队列程序源码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/msg.h>
#define MAX 100
struct msgBuff{
long mType;
char data[MAX];
};
void childProcessfunc(int i, int mgsId){
switch(i){
FILE *pFile; //clear the file pointer
case 1:
printf("welcome in child process one:\n open the file of 2.txt...\n");
sleep(1);
//open the file of 1.txt, program will create this file when it's not existed, otherwise rewrite it.
pFile = fopen("2.txt","w");
fwrite("hello, childTwo, this is childOne!",1,strlen("hello, childTwo, this is childOne!"),pFile);
fclose(pFile); //close file
printf(" close the file and Sending message to childTwo...\n");
struct msgBuff msg1;
msg1.mType=getppid(); //get the parent process's ID
strcpy(msg1.data,"OK");
if (msgsnd(mgsId,&msg1,sizeof(msg1.data),0)<0){
printf("Sending error!\n");
exit(1);
}else{
printf("Sending complete!\n");
}
break;
case 2:
wait(NULL);
printf("welcome in child process two:\n Receiving the message.....\n");
sleep(1);
struct msgBuff msg2;
//receive failed
if (msgrcv(mgsId,&msg2,MAX,getppid(),0)<0){
printf("Receiving error!\n");
exit(1);
}else{
printf("Receiving complete!\n open the file of 2.txt...\n");
//compare the message received with "Ok"
if(strcmp(msg2.data, "OK") == 0){
//open 2.txt
if(NULL == (pFile = fopen("2.txt", "r"))){
printf("open file error\n");
exit(1);
}else{
printf("the content of 2.txt is: ");
}
char ch;
//read 2.txt and output a char at once
while(EOF != (ch=fgetc(pFile))){
printf("%c", ch);
}
fclose(pFile); //close file
}
}
break;
}
exit(0);
}
int main(){
key_t key;
if((key=ftok("/tmp",'g'))<0){
printf("Getting key error!\n");
return -1;
}
int mgsId;
if ((mgsId=msgget(key,IPC_CREAT|0666))==-1){
printf("mgs queue create error!\n");
return -1;
}
//create two child process No.1 and No.2
for (int i = 1; i <= 2; i++){
pid_t child=fork();
//create process failed
if (child==-1)
{
printf("Error hanppened in fork function!\n");
return 0;
}
//exert function when success
else if(child==0)
{
childProcessfunc(i,mgsId);
}
//parent wait for child process
pid_t tempPid=wait(NULL);
}
return 0;
}