当前位置: 首页 > article >正文

Linux IPC:管道符的实现

目录

  • 一、了解管道符
  • 二、实现管道符

  本文主要了解如何模拟实现管道符,要使用的知识点:管道符、匿名管道、输出/输入重定向、程序替换。

一、了解管道符

管道符:|

  管道符的作用可以结合下面的例子来了解一下:

  • ps -ef | grep ./test

  ps -ef:打印系统中的进程信息到标准输出。

  grep ./test:搜索文件中包含./test的行并打印

  管道符的作用就是将 ps -ef 中原本要打印到标准输出的信息转交给 grep ./test,然后grep程序就把这些信息中包含有./test的行打印出来。

二、实现管道符

来看看管道符的模拟实现流程:

  因为我们使用的是匿名管道,因此首先要在父进程中创建匿名管道,然后才可以创建子进程,这样子进程就可以与父进程访问同一个匿名管道。

  由于程序中涉及到两个程序:ps和grep,因此我们要创建两个子进程p1和p2。两个子进程的作用就是进行程序替换,一个运行ps程序,一个运行grep程序。

  ps程序会把数据输出到标准输出,grep原本会从标准输出中接收数据并筛选,管道符将它们连接起来。

  我们将子进程p1和p2进行程序替换后,两个进程之间无法直接传递数据,因此需要使用匿名管道来进行数据的传输。ps子进程将数据发送到匿名管道,grep子进程从匿名管道读取数据并筛选。因此两个子进程还需要进行输入输出重定向才可以实现上面的功能。

  子进程p1:首先进行输出重定向,将原本要输出到标准输出的数据发送到匿名管道,然后进行程序替换运行ps程序。

  子进程p2:首先进行输入重定向,将原本要从标准输入读取的数据改成从匿名管道读取,然后进行程序替换运行grep程序。

  注意:ps程序在将数据发送到匿名管道后就会退出,但grep程序会一直等待,因为如果管道的写端没有全部关闭,管道的读端就不会退出。因此如果要想让grep程序打印完后退出,就要关闭所有写端(包括父进程的)。

为什么程序替换后,输入输出重定向依然有效?

 因为程序替换更新的是虚拟地址空间,页表信息,但IO信息不会初始化。

 如下是模拟实现管道符的代码:

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

//使用匿名管道实现管道符
// ps -ef | grep realiz_pipe
int main(){
  int pipefd[2];//输出参数
  int ret = pipe(pipefd);//创建匿名管道
  if(ret == -1){
    printf("匿名管道创建失败\n");
    return -1;
  }

  pid_t p1 = fork();//创建子进程p1运行ps
  if(p1 == 0){
    dup2(pipefd[1],1);//输出重定向
    execlp("ps","ps","-ef",NULL);//进行程序替换
    exit(-1);//替换失败才会运行到这里
  }
  
  pid_t p2 = fork();//创建子进程p2运行grep
  if(p2 == 0){
    close(pipefd[1]);//关闭写端,否则grep会一直等待
    dup2(pipefd[0],0);//输入重定向
    execlp("grep","grep","realiz_pipe",NULL);//进行程序替换
    exit(-1);
  }
  close(pipefd[0]);
  close(pipefd[1]);//所有写端都被关闭后,读端才会关闭
  wait(NULL);//处理退出的子进程
  wait(NULL);
}


http://www.kler.cn/a/1472.html

相关文章:

  • Python教程丨Python环境搭建 (含IDE安装)——保姆级教程!
  • GO随记:不使用主键id 如何分表与mysql大表
  • ue5 蒙太奇,即上半身动画和下半身组合在一起,并使用。学习b站库得科技
  • USB 驱动开发 --- Gadget 设备连接 Windows 免驱
  • Flutter:封装一个自用的bottom_picker选择器
  • Java语法总结
  • 数据大放送之历史影像下载
  • SpringCloud微服务技术栈.黑马跟学(三)
  • Python04 数据序列-字符串
  • 动态规划-基础(斐波那契数、爬楼梯、使用最小花费爬楼梯、不同路径、不同路径II、整数拆分、不同的二叉搜索树)
  • Leetcode 6322. 检查骑士巡视方案 暴力模拟法 第337场周赛,第二题
  • Java学习星球,Java学习路线
  • 【数据结构】第三站:单链表
  • C语言实现单链表(超多配图,这下不得不学会单链表了)
  • 如何通过openssl生成公钥和私钥?
  • 人脸活体检测系统(Python+YOLOv5深度学习模型+清新界面)
  • elasticsearch 环境搭建和基本操作
  • ETH RPC搭建
  • echart图表之highcharts
  • vue2前端实现html导出pdf功能
  • 灾难性遗忘(catastrophic forgetting)学习笔记
  • Linux中的标准IO【上】
  • FPGA纯verilog实现RIFFA的PCIE通信,提供工程源码和软件驱动
  • C++ 手撸简易服务器(完善版本)
  • 写CSDN博客两年半的收获--总结篇
  • Python3实现AI版贪吃蛇