linux系统编程之管道(一):匿名管道(pipe)
一,什么是管道
管道是Linux支持的最初Unix IPC形式之一,具有以下特点:
- 管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道;
- 只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程);
- 单独构成一种独立的文件系统:管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,它不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且只存在与内存中。
- 数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
管道的实现机制:
管道是由内核管理的一个缓冲区,相当于我们放入内存中的一个纸条。管道的一端连接一个进程的输出。这个进程会向管道中放入信息。管道的另一端连接一个进程的输入,这个进程取出被放入管道的信息。一个缓冲区不需要很大,它被设计成为环形的数据结构,以便管道可以被循环利用。当管道中没有信息的话,从管道中读取的进程会等待,直到另一端的进程放入信息。当管道被放满信息的时候,尝试放入信息的进程会等待,直到另一端的进程取出信息。当两个进程都终结的时候,管道也自动消失。
二,管道的创建(pipe)
包含头文件<unistd.h>
功能:创建一无名管道
原型:
int pipe(int fd[2]);
参数:
fd:文件描述符数组,其中fd[0]表示读端, fd[1]表示写端
返回值:成功返回0,失败返回错误代码
man帮助说明:
DESCRIPTION
pipe() creates a pipe, a unidirectional data channel that can be used
for interprocess communication. The array pipefd is used to return
two file descriptors referring to the ends of the pipe. pipefd[0]
refers to the read end of the pipe. pipefd[1] refers to the write
end of the pipe. Data written to the write end of the pipe is
buffered by the kernel until it is read from the read end of the
pipe. For further details, see pipe(7).
该函数创建的管道的两端处于一个进程中间,在实际应 用中没有太大意义,因此,一个进程在由pipe()创建管道后,一般再fork一个子进程,然后通过管道实现父子进程间的通信(因此也不难推出,只要两个 进程中存在亲缘关系,这里的亲缘关系指的是具有共同的祖先,都可以采用管道方式来进行通信)。父子进程间具有相同的文件描述符,且指向同一个管道pipe,其他没有关系的进程不能获得pipe()产生的两个文件描述符,也就不能利用同一个管道进行通信。
创建管道后示意图:
三,利用管道进行父子进程间数据传输
示例一:子进程向管道中写数据,父进程从管道中读出数据
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h> int main(void)
{
int fds[2];
if(pipe(fds) == -1){
perror("pipe error");
exit(EXIT_FAILURE);
}
pid_t pid;
pid = fork();
if(pid == -1){
perror("fork error");
exit(EXIT_FAILURE);
}
if(pid == 0){
close(fds[0]);//子进程关闭读端
write(fds[1],"hello",5);
exit(EXIT_SUCCESS);
} close(fds[1]);//父进程关闭写端
char buf[10] = {0};
read(fds[0],buf,10);
printf("receive datas = %s\n",buf);
return 0;
}
结果:

示例二:利用管道实现ls |wc –w功能
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h> int main(void)
{
int fds[2];
if(pipe(fds) == -1){
perror("pipe error");
exit(EXIT_FAILURE);
}
pid_t pid;
pid = fork();
if(pid == -1){
perror("fork error");
exit(EXIT_FAILURE);
}
if(pid == 0){ dup2(fds[1],STDOUT_FILENO);//复制文件描述符且指定新复制的fd为标准输出
close(fds[0]);//子进程关闭读端
close(fds[1]);
execlp("ls","ls",NULL);
fprintf(stderr,"exec error\n");
exit(EXIT_FAILURE);
} dup2(fds[0],STDIN_FILENO);
close(fds[1]);//父进程关闭写端
close(fds[0]);
execlp("wc","wc","-w",NULL);
fprintf(stderr, "error execute wc\n");
exit(EXIT_FAILURE);
}
结果:

linux系统编程之管道(一):匿名管道(pipe)的更多相关文章
- Linux系统编程之匿名管道
1.进程间通信介绍 1.1 进程通信的基本概念 在之前我们已经学习过进程地址空间.Linux 环境下,进程地址空间相互独立,每个进程各自有不同的用户地址空间.任何一个进程的全局变量在另一个进程中都看不 ...
- linux系统编程之管道(三)
今天继续研究管道的内容,这次主要是研究一下命名管道,以及与之前学过的匿名管道的区别,话不多说,进入正题: 所以说,我们要知道命名管道的作用,可以进行毫无关系的两个进程间进行通讯,这是匿名管道所无法实现 ...
- Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道
Linux 系统编程 学习:02-进程间通信1:Unix IPC(1)管道 背景 上一讲我们介绍了创建子进程的方式.我们都知道,创建子进程是为了与父进程协作(或者是为了执行新的程序,参考 Linux ...
- Linux 系统编程
简介和主要概念 Linux 系统编程最突出的特点是要求系统程序员对它们工作的的系统的硬件和操作系统有深入和全面的了解,当然它们还有库和系统调用上的区别. 系统编程分为:驱动编程.用户空间编程和网络编程 ...
- 读书笔记之Linux系统编程与深入理解Linux内核
前言 本人再看深入理解Linux内核的时候发现比较难懂,看了Linux系统编程一说后,觉得Linux系统编程还是简单易懂些,并且两本书都是讲Linux比较底层的东西,只不过侧重点不同,本文就以Linu ...
- Linux系统编程@进程通信(一)
进程间通信概述 需要进程通信的原因: 数据传输 资源共享 通知事件 进程控制 Linux进程间通信(IPC)发展由来 Unix进程间通信 基于System V进程间通信(System V:UNIX系统 ...
- linux系统编程之框架
linux系统编程之框架: 1. 进程 1.1 进程概念 1.1.1 PCB 1.1.2 环境变量 1.2 进程控制 1.3 进程间通信 1.3.1 管道 1.3.2 有名管道 1.3.3 共享内存 ...
- linux系统编程(一)概述
glibc库封装了linux系统调用,并提供c语言接口 所以学习linux系统编程,主要参考glibc库系统调用相关api 一.进程控制: fork 创建一个新进程 clone 按指定条件创建子进程 ...
- linux系统编程综合练习-实现一个小型的shell程序(一)
之前已经花了不少篇幅学习了linux系统编程的很多知识点:文件与io.进程.信号.管道,而零散的知识点,怎么能够综合的串接起来是学习的一个很重要的目的,当然最好的方式就是用所学的知识点做一个项目了,所 ...
- Linux 系统编程 学习 总结
背景 整理了Liunx 关于 进程间通信的 很常见的知识. 目录 与 说明 Linux 系统编程 学习:000-有关概念 介绍了有关的基础概念,为以后的学习打下基础. Linux 系统编程 学习:00 ...
随机推荐
- jquery 不选择第一个
参考 https://zhidao.baidu.com/question/174343639.html th:not(':first')
- 快速上手Vue
课程目录: ES6常用语法 Vue基础以及指令 Vue组件 Vue-Router Vue生命周期 npm webpack vue-cli Vuex以及axios
- The Closest M Points
The Closest M Points http://acm.hdu.edu.cn/showproblem.php?pid=4347 参考博客:https://blog.csdn.net/acdre ...
- The valid characters are defined in RFC 7230 and RFC 3986
网上大都说什么发送格式与协议定义的不兼容,改tomcat版本或改编码之类的. 本人测试的时候换了个浏览器,不用IE就好了 如果坚持用ie,也有解决方式 @参考文章 成功的方法 在请求地址var url ...
- 43-python-自己的词典
可以用python实现一个自己的词典, 就是在网上下一个英汉词典,作为自己的词库,然后整理出一个json文件,存起来,查词时,直接读取查询: 处理时可以用正则表达式处理: https://www.cn ...
- php 利用http上传协议(表单提交上传图片 )
主要就是利用php 的 fsocketopen 消息传输. 这里先通过upload.html 文件提交,利用chrome抓包,可以看到几个关键的信息. 首先指定了表单类型为multipart/form ...
- 一个新的threejs理论基础学习网站
网站: https://webglfundamentals.org/
- python性能测试大致计划
hi guy: 如果注意到创建时间,那就对了.这份文章,是我学习Python一个月以后动手写的. 写下这份计划以后,只完成了第一步,其中磕磕绊绊编写代码的过程,很大一部分时间是完全用txt写的 ...
- Oracle SQL 硬解析和子游标
Oracle SQL 硬解析和子游标 What reasons will be happening sql hard parse and generating new child cursors 在一 ...
- pageX/pageY,screenX/screenY,clientX/clientY的差别
pageX/pageY,screenX/screenY,clientX/clientY的差别 $(document).click(function(e){ //x方向无差别 //alert(e.pag ...
