管道单向的、先进先出的、无结构的、固定大小的字节流,它把一个进程的标准输出和另一个进程的标准输入连接在一起。写进程在管道的尾端写入数据,读进程在管道的首端读出数据。数据读出后将从管道中移走,其它读进程都不能再读到这些数据。管道提供了简单的流控制机制。进程试图读空管道时,在数据写入管道前,进程将一直阻塞。同样,管道已经满时,进程再试图写管道,在其它进程从管道中移走数据之前,写进程将一直处于阻塞状态。
管道主要用于不同进程间通信。

下面介绍管道的使用方法:

管道创建:

 #include <unistd.h>
int pipe(int fd[]);

它接收一个参数,也就是包括两个整数的数组。如果系统调用成功,此数组将包括管道使用的两个文件描述符。创建一个管道之后,一般情况下进程将产生一个新的进程。
系统调用:pipe();
原型:int pipe(int fd[2]);
返回值:成功返回0,失败返回-1。

fd[1]写,fd[0]读。

如下图所示,管道是在内核空间的内存中创建的。

单个进程的管道几乎没有任何用处,通常,调用pipe的进程接着调用fork,这样就创建了父子进程间的管道。

 #include <unistd.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h> int main()
{
int fd[];
char buf[];
pid_t pid;
pipe(fd);
pid = fork();
if(pid>)
{//父进程
printf("Father thread\n");
char s[]="Hello\n";
write(fd[],s,sizeof(s));
close(fd[]);
close(fd[]);
}
else if(pid==)
{
printf("Child Thread\n");
read(fd[],buf,sizeof(buf));
printf("%s\n",buf);
close(fd[]);
close(fd[]);
}
waitpid(pid,NULL,);//等待子进程结束
return ;
}

运行结果:

Father thread
Child Thread
Hello

当管道的一端关闭时:
当读一个写端关闭的管道时,则认为已经读到了数据的末尾,读函数返回的读出字节数为0;
当写一个读端关闭的管道时,向管道中写入数据的进程将收到内核传来的SIFPIPE信号,应用程序可以处理该信号,也可以忽略(默认动作则是应用程序终止)。

从管道中读取数据:
当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的数据字节数,如果请求的字节数目不大于PIPE_BUF,则返回管道中现有数据字节数(此时,管道中数据量小于请求的数据量);或者返回请求的字节数(此时,管道中数据量不小于请求的数据量)。注:PIPE_BUF在include/linux/limits.h中定义。

向管道中写入数据:
向管道中写入数据时,linux将不保证写入的原子性,管道缓冲区一有空闲区域,写进程就会试图向管道写入数据。如果读进程不读走管道缓冲区中的数据,那么写操作将一直阻塞。

管道因为没有名字所以只能用于具有亲缘关系的进程,而命名管道(FIFO)则克服了这个限制。

命名管道和一般的管道基本相同,但也有一些显著的不同:
·命名管道是在文件系统中作为一个特殊的设备文件而存在的。
·不同祖先的进程之间可以通过管道共享数据。
·当共享管道的进程执行完所有的I/O操作以后,命名管道将继续保存在文件系统中以便以后使用。
·通过FIFO,不相关的进程也可以交换数据。

下面是命名管道的使用方法:

命名管道创建:

 #include <sys/types.h>
#include<sys/stat.h>
Int mkfifo(const char * pathname, mode_t mode);

返回:成功返回0,出错返回-1。
注:一旦已经用mkfifo创建一个FIFO,就可以用open打开。一般的文件I/O函数close, read , write等都可以用于FIFO。

[OS] 进程间通信--管道的更多相关文章

  1. Linux进程间通信-管道深入理解(转)

    原文地址:https://www.linuxidc.com/Linux/2018-04/151680.htm Linux进程通信系列文章将详细介绍各种通信方式的机制和区别 1.进程间通信 每个进程各自 ...

  2. 详解linux进程间通信-管道 popen函数 dup2函数

    前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统.本章将说明进程之间相互通信的其他技术-I P C(InterProcess Communication ...

  3. Linux进程间通信 -- 管道(pipe)

    前言    进程是一个独立的资源管理单元,不同进程间的资源是独立的,不能在一个进程中访问另一个进程的用户空间和内存空间.但是,进程不是孤立的,不同进程之间需要信息的交互和状态的传递,因此需要进程间数据 ...

  4. Linux进程间通信—管道

    Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  5. Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字

    Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...

  6. Linux进程间通信---管道和有名管道

    一.管道 管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道 传递数据的单向性,管道又称为半双工管道.进程的亲缘关系通常是指父子进程关系. 管道的特点决 ...

  7. 【linux高级程序设计】(第九章)进程间通信-管道 3

    有名管道 无名管道和有名管道: 1. 管道是特殊类型的文件,在满足先入先出的原则写可以读写,不能定位读写位置. 2.管道是单向的. 3.无名管道阻塞于读写位置,而有名管道阻塞在创建位置. 4.无名管道 ...

  8. linux学习:进程间通信—管道

    1.进程间通信当中一种比較简单的方法是管道操作 /* ========================================================================= ...

  9. Linux 进程间通信(管道、共享内存、消息队列、信号量)

           进程通信 : 不同进程之间传播或交换信息    为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...

随机推荐

  1. MQTT客户端

    MQTT客户端 最近公司项目中使用到了一个MQTT的协议,用这个通讯协议将嵌入式端收集到的数据接入到物联网中,很是方便的解决了,嵌入式端存储空间小,也解决了用户需要自定义使用这些记录数据的需求.而且相 ...

  2. C#、C++、Java、Python 选择哪个好?

    C#.C++.Java.Python 选择哪个好? 2019年03月06日 16:54:34 编程小火车 阅读数:214   首先排除Python,光动态语言一个理由,就已经万劫不复了.无论有多少所谓 ...

  3. BZOJ2659_算不出的算式_KEY

    题目传送门 其实打表找一找规律可以得出: /************************************************************** Problem: 2659 U ...

  4. LeetCode:36. Valid Sudoku(Medium)

    1. 原题链接 https://leetcode.com/problems/valid-sudoku/description/ 2. 题目要求 给定一个 9✖️9 的数独,判断该数独是否合法 数独用字 ...

  5. VINS(七)estimator_node 数据对齐 imu预积分 vision

    首先通过vins_estimator mode监听几个Topic(频率2000Hz),将imu数据,feature数据,raw_image数据(用于回环检测)通过各自的回调函数封装起来 ros::Su ...

  6. Java Swing学习笔记——创建JFrame

    创建显示一个空JFrame import javax.swing.JFrame; public class JFrameDemo extends JFrame{ public JFrameDemo() ...

  7. spring入门(Ioc的理解)

    spring对依赖的注入理解可以参考这篇:https://www.cnblogs.com/alltime/p/6729295.html 依赖注入和控制反转 传统的JavaEE程序中,直接在内部new一 ...

  8. matlab画图:设置y轴位置,使y轴在x轴的中间

    sigmoid函数图像 x=-10:0.1:10;  y=sigmf(x,[1 0]);  plot(x,y) 画出的图像如下所示: 怎么将Y轴放在中间呢,而不是在左边? 即如何得到这种效果呢? 方法 ...

  9. RL_Learning

    Key Concepts in RL 标签(空格分隔): RL_learning OpenAI Spinning Up原址 states and observations (状态和观测) action ...

  10. es6从零学习(五):Module的语法

    es6从零学习(五):Module的语法 ES6 模块的设计思想,是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量 一:es6模块化和 CommonJS 和 AMD 模块 (运行 ...