【操作系统】进程间通信

一、实验目的
1. 了解管道通信的特点,掌握管道通信的使用方法。
2. 了解消息队列通信机制及原理,掌握消息队列相关系统调用的使用方法及功能。
二、实验项目内容

管道通信
1. 父进程创建管道和两个子进程p1和p2
2. 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数
据,写完关闭文件,然后向管道写入一条消息“ok”,目的是通知进程p2可以读取文件内容了。
3. 子进程p2通过管道读取消息,如果消息是“ok”,则打开文件,读取文件内容,并将其输出到屏幕上,关闭文件.

消息队列
1. 父进程创建管道和两个子进程p1和p2
2. 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向消息队列写入一条消息“ok”,目的是通知进程p2可以读取文件内容了
3. 子进程p2从消息队列读取消息,如果消息是“ok”,则打开文件,读取文件内容,并将其输出到屏幕上,关闭文件.

三、试验过程及算法

(一) 实验流程图
这里写图片描述

这里写图片描述
(二) 实验过程及算法

两个程序过程和算法相似,因为是比较两种不同的通信方式,大致过程如下:
  1. 父(主)进程创建管道和两个子进程p1和p2;
  2. 子进程p1打开给定文件(如果没有,则创建文件),并向文件中写数据,写完关闭文件,然后向消息队列或管道写入一条消息“ok”,目的是通知进程p2可以读取文件内容了;
  3. 子进程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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿周周

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值