Linux系统中的管道通信

article/2025/9/23 0:47:16

目录

管道如何通信

管道的访问控制机制:

匿名管道

匿名管道数据传输的原理

如何使用(代码案例)

用C/C++代码编译实现父子进程间通信案例 :

思路

实现

命名管道

为什么要有命名管道

回归进程间通信的本质

匿名管道的短板

命名管道的原理

如何创建命名管道

如何使用(代码案例)

用C/C++代码编译实现 client进程 和 server进程的通信案例 :

思路 

实现


管道如何通信

管道,是Linux下常用的进程间通信手段,具体的通信方法是 父进程打开管道文件,被子进程继承,通过文件描述符fd,父子进程能看到相同的内存级文件,而后 一个进程往管道中写,另一个进程读,完成信息的传送。

而打开管道文件与普通文件不同的是,前者具有访问控制,即同步和互斥机制,也就是具有原子性:

管道的访问控制机制:

1.从管道中读取数据时,如果管道为空,或正在被写入,执行读取的进程会阻塞等待

2.往管道中写入数据时,如果管道满了,或正在被读取,执行写入的进程会阻塞等待

3.当写端关闭后,读端读取到EOF 

以上三点机制,使得管道能像文件一样操作的同时,避同时免了使用普通文件进程间通信的 极度的 不安全性。并且,数据在管道文件中的读写是彻底的内存级别的,即不与磁盘交互,读和写皆是在内存中,效率也有一定的保证。

注意管道文件只是单向的,也就是一个进程读,一个进程写的模式,原生规定好的,使用需要符合规范

匿名管道

匿名管道数据传输的原理

匿名管道的通信特点是,通过系统调用pipe(int fd[2]),直接在内核中创建一个内存级文件,并自动被调用它的函数分别以读和写的方式打开两次,获得两个fd。存放在输出型参数fd数组中,fd[0]代表读端fd,fd[1]代表写端fd。两个参与通信的进程能分别通过readwrite这样的系统调用接口,以文件的方式对管道进行读写操作,实现数据的传递。

pipe在内存中创建匿名管道文件

如何使用(代码案例)

用C/C++代码编译实现父子进程间通信案例 :

1.子进程 进程从标准输入按行读取信息

2.通过管道传入到父进程进程中

3.由父进程进程读取并输出到标准输出流。

思路

1.调用pipe(int*fd[2])创建匿名通信管道

2.fork()创建子进程,子进程会继承fd[2]。

子进程:

  (1)关闭读端:close(fd[0])

注:管道只支持单向通信,这里要求子写父读,你也可以实现为父写子读.

  (2)从标准输入(键盘)读取按行读入

  (3)将从键盘读入的内容写入管道

父进程

(1)关闭写端 close(fd[1])

(2)从管道读取数据知道读到文件结尾

(3)等待子进程退出

实现

#include<string.h>
#include<stdlib.h>
#include<errno.h>
#include<assert.h>
#include<stdio.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<unistd.h>#define buffer_size (128)
int main(){int fd[2]={0,0};int pipe_ret=pipe(fd);if(pipe_ret) return errno;//调用出错返回错误码pid_t child_pid=fork();if(child_pid==-1) return errno;if(child_pid==0){//child//关闭不需要的端口close(fd[0]);char child_buffer[buffer_size];while(1){//从键盘读入数据ssize_t read_size=read(0,child_buffer,buffer_size-1);//保证安全性assert(read_size<buffer_size);  child_buffer[read_size]=0;//结束条件if(strcmp(child_buffer,"_exit\n")== 0)break;//发送给父进程write(fd[1],child_buffer,read_size+1);}close(fd[1]);exit(0);}else{//fatherclose(fd[1]);char father_buffer[buffer_size];       while(1){//从管道读取数据ssize_t read_size=read(fd[0],father_buffer,buffer_size-1);//判断是否为文件结尾(子进程关闭写端)if(read_size==0)break;//保证安全性assert(read_size<=buffer_size);//输出内容  printf("父进程收到:%s",father_buffer);}close(fd[0]);//回收子进程pid_t wait_ret=waitpid(child_pid,(int*)0,0);if(wait_ret==-1) return errno;       }return 0;
}

运行效果:

  

命名管道

为什么要有命名管道

回归进程间通信的本质

首先明确 进程间通信的本质是 "让不同的进程,访问到同一份资源"

匿名管道的短板

匿名管道如何使不同进程访问到同一份资源?

父进程分别以读和写两次打开管道文件,而后创建子进程继承文件表述符父子进程能够访问到同一份资源此时能够实现一个进程写一个进程读,进而就具备了通信间通信的客观条件。

但是这样通过继承管道文件的文件描述符fd,来访问到同一份资源的方式有一个明显的缺陷,那就匿名管道只能用于有血缘关系的进程间通信

命名管道则解决了这个问题,能让没有血缘关系的进程也能访问到同一个管道文件

命名管道的原理

在磁盘上创建一个命名管道文件,利用文件名来表示管道的唯一性,只要打开相同的文件名,就能访问到相同的管道文件两个进程通过open分别以读和写打开文件,利用write和read就能完成进程间通信,也不需要血缘关系。

需要注意的是,文件名只是用来标识唯一性,数据的传输更匿名管道一样,完全是内存级的

如何创建命名管道

方法一:系统指令 mkfifo

方法二:系统调用 mkfifo(const char* 文件名,mode_t 文件权限)

成功返回0,失败返回-1(包括文件已经存在的情况),并设置好退出码。

如何使用(代码案例)

用C/C++代码编译实现 client进程 和 server进程的通信案例 :

1.client 进程从标准输入按行读取信息

2.通过管道传入到server进程中

3.由server进程读取并输出到标准输出流。

思路 

1.创建 client.c server.c myfifo.hpp 在头文件中定义命名管道的路径

2.client 和 server 都先调用mkfifo。若返回-1根据errno判断是否存在。若errno不为-1则终止进程返回退出码

3.client 调用open 以只写的方式打开,server以只写的方式打开管道文件

4.client调用write server调用read 完成通信

实现

头文件: myfifo.hpp

#pragma once
#include<assert.h>
#include<string.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<sys/fcntl.h>
#include<errno.h>
#include<stdio.h>
//文件路径 隐藏文件
#define fifo_path "./.myfifo"
#define fifo_mode 0666
//缓冲区大小
#define buffer_size 128

源文件:client.c server.c

client.c: 

#include"myfifo.hpp"
int main(){//创建命名管道int mkfifo_ret=mkfifo(fifo_path,fifo_mode);//判断是否存在if(mkfifo_ret==-1&&errno!=EEXIST)return errno;//打开管道 只写int myfifo_fd= open(fifo_path,O_WRONLY);char client_buffer[buffer_size];while(1){//从标准输入读取数据printf("请输入:> ");fflush(stdout);ssize_t read_ret=read(0,client_buffer,buffer_size-1);//保证安全性assert(read_ret<buffer_size);client_buffer[read_ret]=0;//像管道写入write(myfifo_fd,client_buffer,read_ret+1);if(strcmp(client_buffer,"_exit\n")==0)break;}//关闭写端 server会读取到EOFclose (myfifo_fd);return 0;
}

server.c 

#include"myfifo.hpp"
int main(){//创建命名管道int mkfifo_ret=mkfifo(fifo_path,fifo_mode);//判断是否存在if(mkfifo_ret==-1&&errno!=EEXIST)return errno;//打开管道 只读int myfifo_fd= open(fifo_path,O_RDONLY);char server_buffer[buffer_size];//从管道接收数据while(1){ssize_t read_ret=read(myfifo_fd,server_buffer,buffer_size-1);if(read_ret==0)break;//保证安全性assert(read_ret<=buffer_size);//输出到标准输出printf("服务器收到:> %s",server_buffer);}close(myfifo_fd);return 0;
}

运行效果


http://chatgpt.dhexx.cn/article/ffwVkgbT.shtml

相关文章

linux 管道 (单管道与双管道)

管道的局限性&#xff1a; ①数据不能进程自己写&#xff0c;自己读。 ②管道中数据不可反复读取。-旦读走, 管道中不再存在。 ③采用半双工通信方式&#xff0c;数据只能在单方向上流动。 ④只能在有公共祖先的进程间使用管道 单通道将小写字母改为大写例程&#xff1a; #in…

Linux 管道文件

管道分为无名管道和有名管道两种管道&#xff0c;管道文件是建立在内存之上可以同时被两个进程访问的文件。 先来说说有名管道&#xff1a; mkfifo函数创建有名管道&#xff0c;属于系统调用。 在linux操作系统中为实现下述功能&#xff0c; 先创建一个有名管道文件fifo。 …

【Linux】Linux 管道命令Cut、sort、wc、uniq、tee、tr【一】

目录 &#x1f40b;Cut— 根据条件 从命令结果中 提取 对应内容 &#x1f40b;sort—可针对文本文件的内容&#xff0c;以行为单位来排序。 &#x1f40b;wc命令— 显示/统计 指定文件 字节数, 单词数, 行数 信息. &#x1f40b; uniq— 用于检查及删除文本文件中重复出现的…

Linux管道命令(pipe)全

目录 选取命令&#xff1a;cut、grep 传送门 排序命令&#xff1a;sort、wc、uniq 传送门 双向重定向&#xff1a;tee 字符转换命令&#xff1a;tr、col、join、paste、expand 传送门 划分命令&#xff1a;split 传送门 参数代换&#xff1a;xargs 传送门 关于减号…

Linux中管道命令的用法

原文地址&#xff1a;http://blog.csdn.net/wirelessqa/article/details/8968381 一. 管道命令 管道命令操作符是&#xff1a;”|”,它只能处理经由前面一个指令传出的正确输出信息&#xff0c;对错误信息信息没有直接处理能力。然后&#xff0c;传递给下一个命令&#xff0c;…

Linux管道符

管道 1、管道符 管道符&#xff1a;| 作用&#xff1a;管道是一种通信机制&#xff0c;通常用于进程间的通信。它表现出来的形式将前面每一个进程的输出&#xff08;stdout&#xff09;直接作为下一个进程的输入&#xff08;stdin&#xff09;。 2、过滤功能 # ls / | gr…

linux管道相关命令

目标 cutsortwcuniqteetrsplitawksedgrep 准备数据 zhangsan 68 99 26 lisi 98 66 96 wangwu 38 33 86 zhaoliu 78 44 36 maq 88 22 66 zhouba 98 44 46以上是成绩表信息 使用 逗号 分割, 第一列 是 姓名, 第二列是 语文成绩, 第三列是 数学成绩, 第四列是 英语成绩 需求1: …

Linux管道到底能有多快?

【CSDN 编者按】本文作者通过一个示例程序&#xff0c;演示了通过Linux管道读写数据的性能优化过程&#xff0c;使吞吐量从最初的 3.5GiB/s&#xff0c;提高到最终的 65GiB/s。即便只是一个小例子&#xff0c;可它涉及的知识点却不少&#xff0c;包括零拷贝操作、环形缓冲区、分…

linux管道pipe详解

管道 管道的概念&#xff1a; 管道是一种最基本的IPC机制&#xff0c;作用于有血缘关系的进程之间&#xff0c;完成数据传递。调用pipe系统函数即可创建一个管道。有如下特质&#xff1a; 1. 其本质是一个伪文件(实为内核缓冲区) 2. 由两个文件描述符引用&#xff0c;一个表…

Linux管道符|命令使用详解

1. 作用 “|”是Linux管道命令操作符&#xff0c;简称管道符。使用此管道符“|”可以将两个命令分隔开&#xff0c;“|”左边命令的输出就会作为“|”右边命令的输入&#xff0c;此命令可连续使用&#xff0c;第一个命令的输出会作为第二个命令的输入&#xff0c;第二个命令的…

Linux 管道操作符详解

管道操作符 : | 我们在Linux下经常要用到管道操作符&#xff0c;也就是"|"&#xff0c;即一个竖线。 这个操作符的作用对于经常使用Linux的人来说&#xff0c;看上去十分直观&#xff1a; 不就是将前一个指令的结果交给后一个指令吗&#xff1f; 举个例子&#xff…

linux之管道符详解

linux之管道符 ’ | ’ 操作详解 管道符主要用于多重命令处理&#xff0c;前面命令的打印结果作为后面命令的输入。简单点说就是&#xff0c;就像工厂的流水线一样&#xff0c;进行完一道工序后&#xff0c;继续传送给下一道工序处理… 举个栗子&#xff1a;对hello.sh文件进行…

【Linux】Linux的管道

管道是Linux由Unix那里继承过来的进程间的通信机制&#xff0c;它是Unix早期的一个重要通信机制。其思想是&#xff0c;在内存中创建一个共享文件&#xff0c;从而使通信双方利用这个共享文件来传递信息。由于这种方式具有单向传递数据的特点&#xff0c;所以这个作为传递消息的…

【Linux】管道

前言 我和前桌上课传纸条&#xff0c;这是一种通信方式。 而我们为什么能过在上课的时候通信? 因为我们通过在纸条上写字进行了数据的传递。 本质上而言&#xff0c;我们两个都能看见一份公共的资源并对其进行读写&#xff0c;那就是小纸条&#xff01; 进程间通信的本质&a…

【嵌入式总复习】Linux管道详解——管道通信、无名管道、有名管道、具体应用示例

目录 管道1. 管道通信1.1 通信模式1.2 管道通信中特殊的名词 2. 无名管道&#xff08;PIPE&#xff09;2.1 无名管道的通信原理2.2 无名管道特点2.3 如何操作无名管道示例1示例2 3. 有名管道&#xff08;FIFO&#xff09;3.1 有名管道的特点3.2 如何操作有名管道 4. 示例4.1 cu…

linux命令管道工作原理与使用方法

一、管道定义 管道是一种两个进程间进行单向通信的机制。因为管道传递数据的单向性&#xff0c;管道又称为半双工管道。管道的这一特点决定了器使用的局限性。管道是Linux支持的最初Unix IPC形式之一&#xff0c;具有以下特点&#xff1a; *** 数据只能由一个进程流向另一个进程…

Linux管道

目录 1.管道概念 2.管道分类 1.匿名管道 1.基本实现与概念 2.站在文件描述符角度-深度理解管道 3.站在内核角度-管道本质 4.管道读写规则 5.管道属性设置与阻塞验证 6.管道特点(匿名) 2.命名管道 1.创建一个命名管道 2.命名管道的打开规则 3.匿名管道与命名管道的区别…

linux中管道的概念,浅谈Linux管道

通过前面的学习&#xff0c;我们已经知道了怎样从文件重定向输入&#xff0c;以及重定向输出到文件。Shell 还有一种功能&#xff0c;就是可以将两个或者多个命令&#xff08;程序或者进程&#xff09;连接到一起&#xff0c;把一个命令的输出作为下一个命令的输入&#xff0c;…

linux管道举例理解

linux管道举例理解 一、管道的定义&#xff1a;“|”二、查找2.1统计当前目录下有多少个文件2.2查看当前目录下的前n&#xff08;3&#xff09;个文件2.3查看wang.txt文件包含i的字符行2.4查看内存使用情况2.5查询进程 三、更改 https://blog.csdn.net/hanhanwanghaha宝藏女孩 …

图解YUV格式

YUV格式有两大类&#xff1a;planar和packed。 对于planar的YUV格式&#xff0c;Y&#xff0c;U&#xff0c;V都是连续存放的&#xff0c;比如 YYYYUUUUVVVV 对于packed的YUV格式&#xff0c;每个像素点的Y,U,V是连续交替存储的。 RGB24&#xff0c;BGR24等等都是packed方式存…