Linux进程间通信 -- 管道(pipe)
前言
进程是一个独立的资源管理单元,不同进程间的资源是独立的,不能在一个进程中访问另一个进程的用户空间和内存空间。但是,进程不是孤立的,不同进程之间需要信息的交互和状态的传递,因此需要进程间数据的传递、同步和异步的机制。
当然,这些机制不能由哪一个进程进行直接管理,只能由操作系统来完成其管理和维护,Linux提供了大量的进程间通信机制,包括同一个主机下的不同进程和网络主机间的进程通信,如下图所示:

- 同主机间的信息交互:
- 无名管道:
特点:多用于亲缘关系进程间通信,方向为单向;为阻塞读写;通信进程双方退出后自动消失
问题:多进程用同一管道通信容易造成交叉读写的问题- 有名管道:
FIFO(First In First Out),方向为单向(双向需两个FIFO),以磁盘文件的方式存在;通信双方一方不存在则阻塞- 消息队列:
可用于同主机任意多进程的通信,但其可存放的数据有限,应用于少量的数据传递- 共享内存:
可实现同主机任意进程间大量数据的通信,但多进程对共享内存的访问存在着竞争
- 同主机进程间同步机制:信号量(Semaphore)
- 同主机进程间异步机制:信号(Signal)
- 网络主机间数据交互:Socket(套接字)
1. 无名管道
1). 概念
无名管道是一类特殊的文件,在内核中对应着一段特殊的内存空间,内核在这段内存空间中以循环队列的方式存储数据;
无名管道的内核资源在通信双方退出后自动消失,无需人为回收;
无名管道主要用于连通亲缘进程(父子进程),用于双方的快捷通信,通信为单向通信
2). 操作
1. 创建:
pipe()
头文件:
#include <unistd.h>
函数原型:
int pipe(int pipedes[2])
参数:
pipedes[2]:存储文件描述符
- 返回值:
成功:0
失败:-1
2. 读写:
| 读进程 | 写进程 | 管道无数据 | 管道有数据 |
|---|---|---|---|
| 阻塞√ | 立刻返回0 | 返回数据 | |
| 阻塞√ | √ | 读阻塞 | 读数据并返回 |
| 阻塞√ | 收到SIGPIPE信号,write返回-1 |
||
| √ | 阻塞√ | 写入 | 若满,阻塞等待 |
3. 重定向:
所谓重定向,即关闭某个标准I/O设备(stdin(0), stdout(1), stderr(2)), 而将某一个普通的文件描述符设置为0/1/2.
重定向,主要是采用 dup函数来实现的:
- dup函数:

作用:
复制文件描述符头文件:
#include <unistd.h>
函数原型:
函数 原型 描述 dup int dup(int oldfd) 复制oldfd文件表项,并返回未用的最小值描述符 dup2 int dup2(int oldfd, int newfd) 复制oldfd文件表项到newfd,newfd为用户自定义值,而后关闭oldfd 参数:
oldfd:源文件的描述符(要求该文件描述符必须有效,文件必须处于打开状态)
newfd:新的文件描述符,个人理解为oldfd的软链接
- 返回值:
成功:最小值文件描述符(dup) / newfd的值(dup2)
失败:-1
2. 有名管道
1). 概念
又称FIFO(Fisrt In First out), 是磁盘上的一个特殊文件,没有在磁盘存储真正的信息,其所存储的信息在内存中
通信双方进程结束后,自动丢弃FIFO中的信息,但其在磁盘的文件路径本身依然存在
2). 操作
1. 创建 - mkfifo()
头文件:
#include <sys/stat.h>
函数原型:
int mkfifo(const char *pathname, mode_t mode)
参数:
pathname: FIFO文件
mode: 创建文件的属性(权限)
- 返回值:
成功:0
失败:-1
2. 读写:
| 读进程 | 写进程 | FIFO无数据 | FIFO有数据 |
|---|---|---|---|
| √ | 阻塞 | 阻塞 | |
| √ | 阻塞 | 阻塞 | |
| √ | √ | 写入 | 读出(未满,读写同时) |
| √ | √x | 即写中途退出,读直接返回0 | same |
| √x | √ | 读中途退出,写返回SIGPIPE |
same |
3. 补充
access函数
作用:
检查用户(进程)对文件的权限头文件:
#include <unistd.h>
函数原型:
int access(const char *pathname, int mode)
参数:
pathname: 即文件名
mode:测试的属性
mode description F_OK 该文件是否存在 R_OK 可读 W_OK 可写 X_OK 可执行 bitwise 属性(读/写/执行等)
- 返回值:
成功:0
失败:-1
4. 代码示例
1). PIPE
/*
* Filename: pipe.c
*/
#include <stdio.h>
#include <unistd.h> //for pipe()
#include <string.h> //for memset()
#include <stdlib.h> //for exit()
int main()
{
int fd[2];
char buf[20];
if(-1 == pipe(fd))
{
perror("pipe");
exit(EXIT_FAILURE);
}
write(fd[1], "hello,world", 12);
memset(buf, '\0', sizeof(buf));
read(fd[0], buf, 12);
printf("The message is: %s\n", buf);
return 0;
}
2). FIFO
程序的步骤:
- 创建一个新的fifo文件
- fifo_snd.c文件负责向fifo中写入数据
- fifo_rcv.c负责从fifo中读取数据并打印
1. fifo_snd.c:
/*
*File: fifo_send.c
*/
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h>
#define FIFO "/tmp/my_fifo"
int main()
{
char buf[] = "hello,world";
//`. check the fifo file existed or not
int ret;
ret = access(FIFO, F_OK);
if(ret == 0) //file /tmp/my_fifo existed
{
system("rm -rf /tmp/my_fifo");
}
//2. creat a fifo file
if(-1 == mkfifo(FIFO, 0766))
{
perror("mkfifo");
exit(EXIT_FAILURE);
}
//3.Open the fifo file
int fifo_fd;
fifo_fd = open(FIFO, O_WRONLY);
if(-1 == fifo_fd)
{
perror("open");
exit(EXIT_FAILURE);
}
//4. write the fifo file
int num = 0;
num = write(fifo_fd, buf, sizeof(buf));
if(num < sizeof(buf))
{
perror("write");
exit(EXIT_FAILURE);
}
printf("write the message ok!\n");
close(fifo_fd);
return 0;
}
2. fifo_rcv.c:
/*
*File: fifo_rcv.c
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/ipc.h>
#include <fcntl.h>
#define FIFO "/tmp/my_fifo"
int main()
{
char buf[20] ;
memset(buf, '\0', sizeof(buf));
//`. check the fifo file existed or not
int ret;
ret = access(FIFO, F_OK);
if(ret != 0) //file /tmp/my_fifo existed
{
fprintf(stderr, "FIFO %s does not existed", FIFO);
exit(EXIT_FAILURE);
}
//2.Open the fifo file
int fifo_fd;
fifo_fd = open(FIFO, O_RDONLY);
if(-1 == fifo_fd)
{
perror("open");
exit(EXIT_FAILURE);
}
//4. read the fifo file
int num = 0;
num = read(fifo_fd, buf, sizeof(buf));
printf("Read %d words: %s\n", num, buf);
close(fifo_fd);
return 0;
}
Linux进程间通信 -- 管道(pipe)的更多相关文章
- Linux进程间通信—管道
Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...
- Linux进程间通信:管道,信号量,消息队列,信号,共享内存,套接字
Linux下的进程通信手段基本上是从UNIX平台上的进程通信手段继承而来的.而对UNIX发展做出重大贡献的两大主力AT&T的贝尔实验室及BSD(加州大学伯克利分校的伯克利软件发布中心)在进程间 ...
- linux中管道(pipe)一谈
/*********************************************** 管道(pipe)是Linux上进程间通信的一种方式,其是半双工(数据流只能在一个方向上流动(还需要经过 ...
- Linux进程间通信-管道深入理解(转)
原文地址:https://www.linuxidc.com/Linux/2018-04/151680.htm Linux进程通信系列文章将详细介绍各种通信方式的机制和区别 1.进程间通信 每个进程各自 ...
- Linux进程间通信---管道和有名管道
一.管道 管道:管道是一种半双工的通信方式,数据只能单方向流动,而且只能在具有亲缘关系的进程间使用,因为管道 传递数据的单向性,管道又称为半双工管道.进程的亲缘关系通常是指父子进程关系. 管道的特点决 ...
- 详解linux进程间通信-管道 popen函数 dup2函数
前言:进程之间交换信息的唯一方法是经由f o r k或e x e c传送打开文件,或通过文件系统.本章将说明进程之间相互通信的其他技术-I P C(InterProcess Communication ...
- linux 进程间通信之pipe
在实际开发过程中,程序员必须让拥有依赖关系的进程集协调,这样才能达到进程的共同目标. 每个进程各自有不同的用户地址空间,任何一个进程的全局变量在另一个进程中都看不到,所以进程之间要交换数据必须通过内 ...
- Linux 进程间通信(管道、共享内存、消息队列、信号量)
进程通信 : 不同进程之间传播或交换信息 为什么要进程通信呢? 协同运行,项目模块化 通信原理 : 给多个进程提供一个都能访问到的缓冲区. 根据使用场景,我们能划分为以下几种通信 ...
- linux进程间通信-管道
一 管道的局限性 管道有两个局限性:(1)他是半双工(即数据只能在一个方向上流动).(2)它只能在具有公共祖先的进程之间使用.一个管道由一个进程创建,然后该 进程调用fork,此后父子进程之间就可该管 ...
随机推荐
- (原创)PetaPoco使用小记(2014-5-5更新)
接触PetaPoco已经有一段时间了,为了全面了解一下PetaPoco,刚好结合目前在做的一个项目,对常用的几个业务操作用PetaPoco进行改写,如增删改查.分页以及存储过程的调用,在文章的最后附上 ...
- LinkServer--在Job中使用Linkserver注意事项
如果要使用job来调用link server的话,不能使用作业步骤属性高级选项中”作为以下用户运行“来以本地登录用户模拟远程用户访问远程服务器.会报”无法建立安全上下文“的错误. 将Job中代码封装到 ...
- Global.asax和HttpModule的执行顺序
Application_Start-->用户自定义的HttpModule-->Application_BeginRequest (注册->调用) 看到Init方法(在用户自定义的 ...
- 导出excle错误
导出excel时出现下面的错误: 类型“GridView”的控件“SimpleForm1_ContentPanel2_GVD_List”必须放在具有 runat=server 的窗体标记内. 可以在对 ...
- CC2530学习路线-基础实验-GPIO 按键控制LED灯亮灭(2)
目录 1.前期预备知识 1.1 新大陆Zigbee模块按键电路图 1.2 CC2530相关寄存器 1.3 CC2530中断走向图 1.4 使用C语言为51单片机编写中断程序 1.5 *函数指针 2. ...
- 雨天的尾巴(bzoj3307)(线段树合并+树上差分)
\(N\)个点,形成一个树状结构.有\(M\)次发放,每次选择两个点\(x,y\) 对于\(x\)到\(y\)的路径上(含\(x,y\))每个点发一袋\(Z\)类型的物品.完成 所有发放后,每个点存放 ...
- Zookeeper之Curator(1)客户端基本的创建,删除,更新,查找操作api
Curator Framework提供了简化使用zookeeper更高级的API接口.它包涵很多优秀的特性,主要包括以下三点: 自动连接管理:自动处理zookeeper的连接和重试存在一些潜在的问题: ...
- [bug]小米部分机型(5x、mix2)中,文字/背景闪现然后消失
2/9更新 后来遇到float 元素也这样,改成flex布局就没问题.不知道具体原因. 描述: 使用vue 2.4开发HTML5时,遇到在小米部分机型(5x.mix2)中,文字/文字背景闪现然后消失. ...
- puppet更新失败
# puppet-updatepuppet: no process foundWarning: Unable to fetch my node definition, but the agent ru ...
- python求100以内素数
python求100以内素数之和 from math import sqrt # 使用isPrime函数 def isPrime(n): if n <= 1: return False for ...
