进程间的通信之管道
来源:互联网 发布:小米手机关闭4g网络 编辑:程序博客网 时间:2024/06/06 23:45
一.管道的分类:
管道是进程间通讯的一种(进程间通讯还有:信号,信号量,消息队列,共享存储,套接字),它分为无名管道和有名管道。
有名管道应用于任意俩个进程之间数据的单项传递。
无名管道只能引用于父子进程之间。
二.管道的工作:
1.管道的操作
有名管道 无名管道 创建 mkfifoint pipe(int fd[2])打开openint pipe(int fd[2])写writewrite(fd[1],buff,len)读readread(fd[0],buff,size)关闭closeclose(fd[1]);close(fd[0]);
三.注意
1.有名管道:
1) 在文件目录树中有一个文件标示(管道文件)。实际不占据磁盘空间。
数据缓存在内存上。
2)如果一个进程以只写方式打开一个管道文件,open 会阻塞运行,直到有一个进程
以读方式打开管道文件。open 才会返回,进程才会接着执行。
如果一个进程以只读方式打开一个管道文件,open 会阻塞运行,直到有一个进程
以写方式打开管道文件。open 才会返回,进程才会接着执行。
read 函数也会阻塞运行,直到写端写入数据或者所有的写端都关闭。
read 读取数据并且会将内存上的已读数据清空。
只写,open阻塞运行
直到有一个读端打开管道
2.管道都是半双工通讯,而无名管道创建后,父进程在 fork 产生子进程后,
两个进程分别有一对读写,所以,要在父子进程分别关闭读或写。
四.扩展
1.管道的默认大小是多少??能不能修改管道的大小?
一页,即4K字节。
可以通过修改linux/limits.h/pipe_buff来修改管道大小
2.管道操作的内核实现。(空间的开辟, 读写操作偏移量的变化)
linux下的进程的用户态地址空间都是相互独立的,因此俩个进程是没法直接通信的,因为找不到彼此的存在,儿内核是进程间共享的,因此进程间想通信只能通过内核作为中间人,来传达信息。下图显示了俩个进程间通过内核缓存进行通信的过程:
五.代码
1.有名管道
写端: 读端:
pipe的实现就是和上述图示一样,在pipefs文件系统的inode中有一个属性:struct pipe_inode_info*i_pipe;
这个结构体定义如下:
这个结构体定义了管道的缓存,由base指向,缓存大小为一个内存页,有如下定义:
#define PIPE_SIZEPAGE_SIZE
其实到现在我们大概猜得到管道的是实现原理,在一个进程中,向管道中写入数据时,其实就是写入这个缓存中;然后在另一个进程读取管道时,其实就是从这个缓存读取,实现进程的通信。
这个缓存也可以解释为什么管道是单通道的:因为只有一个缓存,如果是双通道,那么两个进程同时向这块缓存写数据时,这样会导致数据覆盖,即一个进程的数据被另一个进程的数据覆盖.而向套接字有读写缓存,因此套接字是双通道的.
从pipe函数开始,看看内核是如何创建管道的.pipe系统调用在内核对应的服务例程为sys_pipe,在sys_pipe函数中接着调用do_pipe创建两个管道描述符,一个用于写,另一个用于读。
总结下do_pipe函数的执行过程:
1.实例化两个空file结构体;
2.创建带有pipe属性的inode结构;
3.在当前进程文件描述符表中找出两个未使用的文件描述符;
4.为这个inode分配dentry结构体,关联file和inode
5.针对可读和可写file结构,分别设置相应属性,主要是操作函数集合属性
6.关联文件描述符和file结构
7.将两个文件描述符返回给用户;
2.无名管道
遇到并解决的问题:
①。第14行刚开始写成了:pid_t pid=fork()
这样导致fork在管道之前创建,也就是说先有了父子进程才有的管道,那么父子进程都会对管道操作
②。第32行不能用strlen,要用sizeof。用strlen会阻塞,因为一开始读的是0
- 进程间的通信之管道
- 进程间的通信之1-----管道
- 进程间的通信之管道
- [进程通信] 进程间通信 之 管道
- 进程间通信之管道
- 进程间通信之 管道
- 进程间通信 之 管道
- 进程间通信之管道
- 进程间通信之管道
- 进程间通信之 管道
- 进程间通信之管道
- 进程间通信之管道
- 进程间通信之管道
- 进程间通信之管道
- 进程间通信之管道
- 进程间通信之管道
- 进程间通信之--- 管道
- 进程间通信之管道
- mybatis 构造查询和联合子查询问题
- Java项目中文乱码,设置UTF-8
- 目标管理和自我控制
- 基于协同过滤的SVD的推荐系统
- opencv-图像基本操作
- 进程间的通信之管道
- gdb调试动态加载模块
- Android Studio新建的工程继承了AppCompatActivity设置隐藏标题栏后闪退
- Java多线程池的使用
- java 可变类 不可变类区别
- 10K 问题的解决:一个系统管理员如何管理 2000x 台服务器
- android 使用TableLayout 绘制表格
- 学习心得
- SSH登录后无法上传文件,修改sftp-server目录解决