实验报告:利用管道实现进程的通信

实验目的

  • 熟悉 Linux 下的应用程序开发;
  • 熟悉 Linux 的进程控制原语的使用;
  • 掌握 Linux 操作系统的进程间通信机制管道的使用;
  • 掌握 Linux 操作系统中父进程与子进程的同步。

实验原理

每个进程各自有不同的用户地址空间,进程之间要交换数据必须通过内核(内核开辟的缓冲区),内核提供的这种机制称为进程间通信(IPC,InterProcess Communication)。

  1. 管道是一种最基本的 IPC 机制,由 pipe 函数创建:
    int pipe(int fd[2]);
    返回值:成功返回 0,错误返回-1。
    参数 fd 为管道描述符,同文件描述符,可以使用文件 I/O 函数(close, read, write)进行操作。
    fd[0]为管道读端;fd[1]为管道写端。如不需要,可以关闭相应端的描述符。

  2. 管道的读写:
    int close(int fd); //关闭由文件描述符 fd 指定的文件
    ssize_t read(fd, void *buf, size_t count); //读取管道内容
    ssize_t write(fd, void *buf, size_t count); //向管道写内容

  3. 创建父进程和子进程:
    在这里插入图片描述
    父进程关闭写端,子进程关闭读端:
    在这里插入图片描述

  4. 父进程查询子进程的退出:
    子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它只保留最小的一些内核数据结构,以便父进程查询子进程的退出状态。
    调用 wait 函数或者 waitpid 函数查询子进程退出状态,此方法父进程会被挂起。


实验内容

(1)在 Linux 系统中使用系统调用 fork()创建两个子进程;
(2)使用系统调用 pipe()建立一个管道,两个子进程分别向管道各写一句话;
(3)父进程则从管道中读出来自于两个子进程的信息,显示在屏幕上。然后分别结束两个子进程的运行。

  • 要求 1:在 Linux 平台下实现。
  • 要求 2:fork 创建两个子进程。子进程(fork 函数让子进程完整地拷贝了父进程的整个地址空间)都有管道的读端和写端。所以在相关进程中最好关掉不用的那一端。
  • 要求 3:父进程先接收子进程 P1 发来的消息,然后再接收子进程 P2 发来的消息。
  • 存在两个同步问题:
    ①两个子进程和父进程之间(先子写后父读)
    ②子进程 1 和子进程 2 之间(先 1 写,再 2 写)
  • 使用 waitpid 函数实现父进程等待子进程运行完毕后从管道中读取数据并打印,只有子进程将数据写入管道后,父进程才能够执行打开管道操作。

实验器材

硬件环境:个人计算机
操作系统:CentOS 7


实验步骤

(1)进程间管道通信实验步骤:

  1. 创建一个管道;
  2. 创建子进程 1,向管道中写入“Child process 1 is sending a message!”,并做好跟父进程的同步执行;
  3. 创建子进程 2,向管道中写入“Child process 2 is sending a message!”,并做好跟父进程的同步执行;
  4. 父进程从管道中读取数据,并打印输出。

(2)利用管道实现进程的通信的实现流程图
在这里插入图片描述

(3)利用管道实现进程的通信的实现代码

  1. 创建管道。
    在这里插入图片描述

  2. 子进程向管道写内容,父进程读取管道内容。
    用 fork 函数创建子进程 p1 和 p2,p1 进行关闭管道读端、向管道写数据、子进程结束,p2 也同样。然后在父进程中用 waitpid 函数确保子进程写完数据,进行关闭管道写端、从管道读数据、打印结果。
    在这里插入图片描述


实验结果

//Using Pipe to Realize IPC

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/wait.h>

int main() {
    int fd[2];
    if (pipe(fd) == -1)         //创建管道
        return -1;

    pid_t p1, p2;
    if ((p1 = fork()) == 0) {		//子进程p1
        char* msg1 = "Child process 1 is sending a message!\n";
        close(fd[0]);           	//关闭管道读端
        write(fd[1], msg1, strlen(msg1));   //向管道写数据
        return 0;
    }
    else if (p1 > 0) {          	//父进程
        waitpid(p1, NULL, 0);
        if ((p2 = fork()) == 0) {	//子进程p2
            char* msg2 = "Child process 2 is sending a message!\n";
            close(fd[0]);       	//关闭管道读端
            write(fd[1], msg2, strlen(msg2));   //向管道写数据
            return 0;
        }
        else if (p2 > 0) {      	//父进程
            waitpid(p2, NULL, 0);
            char msg[100];
            close(fd[1]);       	//关闭管道写端
            read(fd[0], msg, 100);      //从管道读数据
            printf("%s", msg);
            return 0;
        }
    }
    else
        return -1;
}

在这里插入图片描述
子进程 p1 向管道中写入:Child process 1 is sending a message!
子进程 p2 向管道中写入:Child process 2 is sending a message!
子进程做好跟父进程的同步执行,最后父进程读取管道内容并输出。


操作系统基础实验:

  • 4
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值