
【进程】进程间通信----管道
发布日期:2021-05-10 06:33:24
浏览次数:17
分类:精选文章
本文共 2746 字,大约阅读时间需要 9 分钟。
管道与posix ipc mechanisms
1、管道
什么是管道?
管道是指一个进程与另一个进程之间的一种数据流连接,能够实现进程间的通信。在Unix系统中,管道是最古老的进程间通信机制之一。
2、匿名管道
2.1 匿名管道的本质
匿名管道在内核中开辟一段缓冲区,这段缓冲区没有标识符,也称为“写入缓冲区”。由于匿名管道没有标识符,难以被其他进程直接找到,因此只能在进程之间使用。
2.2 文件描述符数组(fd[2])
fd[0]
:读端文件描述符,用于读取数据。fd[1]
:写端文件描述符,用于写入数据。fd[2]
:文件描述符数组,其真正作用是保存文件描述符。fd[0]
和fd[1]
是被pipe
函数赋予的。
2.3 匿名管道的特性
- 只能用于亲缘关系进程间通信:管道只能在有直接或间接连接的两个进程之间传输数据。
- 单双工通信:数据可以按字节流式发送,读端可以决定读取的数据量。
- 提供流式服务:写端数据被立即传输至读端,读端可以选择读取的字节数和频率。
- 管道跟随进程生命周期:当写进程退出或终止,管道即被销毁。
2.4 容量限制
- 管道默认容量:64k字节。
- 缓冲区大小:4k字节。
- 由于写入字节数通常小于4k,写操作的原子性得到了保证。
2.5 匿名管道的应用示例
#include#include int main() { int fd[2]; if (pipe(fd) < 0) { printf("pipe error\n"); return -1; } // 打印文件描述符 printf("fd[0]: %d\n", fd[0]); printf("fd[1]: %d\n", fd[1]); int child = fork(); if (child < 0) { printf("fork error\n"); return -1; } else if (child == 0) { // 子进程 close(fd[0]); if (write(fd[1], "i love you", 11) < 0) { printf("write error\n"); return -1; } return 0; } else { // 父进程 close(fd[1]); char buff[1024] = {0}; if (read(fd[0], buff, sizeof(buff) - 1) < 0) { printf("read error\n"); return -1; } printf("%s\n", buff); return 0; }}
3、int fcntl(int fd, int cmd, ...)
3.1 调用功能
int fcntl(int fd, int cmd, ...): 将cmd参数传递给fd,并执行相应操作。
F_GETFL
:获取文件描述符属性。F_SETFL
:设置文件描述符属性。如需设置非阻塞属性,将flag"| O_NONBLOCK".
3.2 非阻塞操作
int flag = fcntl(fd, F_GETFL);fcntl(fd, F_SETFL, flag | O_NONBLOCK);
3.3 非阻塞属性设置说明
- 写端非阻塞:关闭读端文件描述符。若尝试读取,进程将收到
SIGPIPE
信号。 - 读端非阻塞:关闭写端文件描述符。若尝试写入,进程将收到
SIGPIPE
信号。
4、命名管道
4.1 命名管道的本质
命名管道也称为fuse
, 它在内核中开辟一段缓存区,并附带标识符。这使得任何具有相同标识符的进程都可以找到该缓存区,无需亲缘关系。
4.2 创建命名管道
- 命令行工具
mkfifo filename
- 程序中创建
int mkfifo(const char *path, mode_t mode);
4.3 命名管道的区别
- 匿名管道:由
pipe
函数创建。 - 命名管道:由
mkfifo
函数创建。
4.4 命名管道的应用示例
#include#include #include int main() { int fifo = mkfifo("./fifo_test", 0664); if (fifo < 0) { printf("mkfifo error\n"); return -1; } char buf[] = "Hello World\n"; int fd = open("./fifo_test", O_RDWR); if (fd < 0) { printf("open error\n"); return -1; } if (write(fd, buf, sizeof(buf) - 1) < 0) { printf("write error\n"); return -1; } char buf2[1024] = {0}; if (read(fd, buf2, sizeof(buf2) - 1) < 0) { printf("read error\n"); return -1; } printf("%s", buf2); return 0;}
5、管道本质
5.1 管道的内部结构
- Linux使用file结构和VFS inode来实现管道。
- 通过将两个file结构指向同一个inode,形成一个临时的缓冲区。
5.2 管道的读写机制
- 写进程将数据复制到共享的物理页面上。
- đọc进程从共享页面读取数据到自己的地址空间。
- 读写操作会唤醒对方,确保流程切换。
5.3 管道的优化
- POSIX标准定义了管道行为,确保不同系统间的一致性。
- 读写端的 suspend/resume 机制优化了资源利用率。
发表评论
最新留言
能坚持,总会有不一样的收获!
[***.219.124.196]2025年04月22日 07时00分47秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
adb通过USB或wifi连接手机
2019-03-11
JDK9-15新特性
2019-03-11
TreeSet、TreeMap
2019-03-11
JVM内存模型
2019-03-11
可变长度参数
2019-03-11
cordova打包apk更改图标
2019-03-11
GitHub上传时,项目在已有文档时直接push出现错误解决方案
2019-03-11
文件系统的层次结构
2019-03-11
vue(渐进式前端框架)
2019-03-11
vscode设置eslint保存文件时自动修复eslint错误
2019-03-11
Remove Extra one 维护前缀最大最小值
2019-03-11
Linux操作系统的安装与使用
2019-03-12
Docker入门之-镜像(二)
2019-03-12
嵌入式系统试题库(CSU)
2019-03-12
setup facatory9.0打包详细教程(含静默安装和卸载)
2019-03-12
Linux kernel pwn --- CSAW2015 StringIPC
2019-03-12
IDEA 找不到 Persistence窗口解决办法
2019-03-12
Form窗体属性
2019-03-12
vue 错误收集
2019-03-12