操作系统实验一:父子进程通信

操作系统实验一:进程的建立


一、 实验目的:

  1. 创建进程及子进程;

  2. 在父子进程之间实现进程通信;

二、 实验内容:

  1. 创建进程并显示标识等进程控制块的属性信息;

  2. 显示进程的通信信息和相应的应答信息;

三、实验要求

  1. 显示创建的进程及控制块参数;

  2. 显示进程之间的关系参数;

  3. 实现父子进程之间通信模拟;

四、实验设计与实现:

  • 设计思路:实验要求在 父子进程 之间实现进程通信,所以可以采用 fork() 函数来通过一个进程创建他的一个子进程。关于父子进程之间通信可以采用 无名管道 这一方式。无名管道是通过内核开辟一段缓存空间,进程共享这段缓存空间,通过文件描述符( write()和read() )对这段缓存空间的读写来实现进程之间的通信。一个无名管道在进程双向通信时有极大可能产生 干扰 (即父进程刚写入的信息在子进程读到之前就又被父进程读到),为了防止干扰,采用了两个 无名管道 实现 父子进程间双向通信。此外,通过 getpid()和getppid() 获取父子进程的pid标识符。

  • 实验环境:Linux系统,Ubuntu 64位 20.04.2.0;

  • 实验代码:

    • Pipe.c:

      #include<stdio.h>
      #include<stdlib.h>
      #include<unistd.h>
      #include<string.h> // for bzero()
      
      /* 
       *该函数用来输出错误信息;
       */
      void print_err(char *estr)
      {
          perror(estr);
          exit(-1);
      }
      
      int main(void)
      {
          int ret = 0; // ret变量用来接收返回值;
      
          /*
           * 用两个数组来存放两个管道的文件描述符;
           * [0]元素:存放读文件描述符;
           * [1]元素:存放写文件描述符; 
           */
          int pipefd1[2] = {0}; 
          int pipefd2[2] = {0};
      
      
          ret = pipe(pipefd1); // 调用pipe函数判断返回值;
          if(ret == -1){print_err("pipe1 fail");}
          ret = pipe(pipefd2); 
          if(ret == -1){print_err("pipe2 fail");}
      
          ret = fork(); // 创建父子进程并判断返回值;
          if(ret == -1){print_err("fork fail");}
      
          if(ret > 0){
      
              /* 
               * 该段代码是父进程执行的;
               */
      
              close(pipefd1[0]); // 关闭父进程管道一的读描述符(防止干扰);
              close(pipefd2[1]); // 关闭父进程管道二的写描述符;
      
              char buf[30] = {0}; // 定义一个缓存字符串组;
              
              int f_pid;
              f_pid = getpid();
              int s_pid;
              s_pid = ret;
              
      
              while(1){
                  printf("\033[35;1m输入父进程(pid=%d)发送的消息:", f_pid);
                  scanf("%s", buf);
                  write(pipefd1[1], buf, sizeof(buf)); // 写入管道1;
                  sleep(1);
                  bzero(buf, sizeof(buf)); // 清空缓存区;
                  read(pipefd2[0], buf, sizeof(buf)); // 读管道2;
                  printf("\033[35;1m父进程(pid=%d)接收子进程(pid=%d)的消息: %s\n", f_pid, s_pid, buf);
              }
          }
          else if(ret == 0){
      
              /* 
               * 该段代码是子进程执行的;
               */
      
              close(pipefd1[1]); //关闭子进程的写描述符;
              close(pipefd2[0]);
              char buf[30] = {0}; // 定义一个缓存字符串组;
              
              int s_pid;
              s_pid = getpid();
              int f_pid;
              f_pid = getppid();
      
              
      
              while(1){
                  bzero(buf, sizeof(buf)); // 清空缓存区;
                  read(pipefd1[0], buf, sizeof(buf));
                  printf("\033[36;1m子进程(pid=%d)接收父进程的消息(pid=%d):%s\n", s_pid, f_pid, buf); 
      
                  sleep(1); 
                  printf("\033[36;1m输入子进程(pid=%d)发送的数据:", s_pid);
                  scanf("%s", buf);
                  write(pipefd2[1], buf, sizeof(buf)); 
              }
          }
          return 0;
      }
      

五、实验结果分析:

  • 在Linux终端中输入:

    gcc pipe.c
    ./a.out
    
  • 终端输出结果:

在这里插入图片描述

  • 在提示下输入字符串,实现了父子进程之间的通信。

参考视频:
https://www.bilibili.com/video/BV1fE411v7Bb?p=6
https://edu.51cto.com/course/13462.html

  • 14
    点赞
  • 85
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值