【Linux】管道文件(有名管道、无名管道)
多进程编程的目的就是为了同时完成多个任务。
例如:一个产品,一个软件,需要n个进程同时执行才能完成,而这些进程之间一定是有所联系的。
因此:多进程工作时,进程间需要通讯(传递数据)。
fork()创建的子进程,与父进程之间唯一共享的是文件描述符。
进程之间的通讯方式有: 管道
信号量
消息队列
共享内存
Socket (用于网络通讯,即不同主机上进程之间的通讯)
关于单工、半双工、全双工通讯
单工通讯:任意时刻,数据流向均为单向
半双工通讯:同一时刻,数据流向为单向(管道文件)
管道
①有名管道(命令管道)
在磁盘上会存储一个管道文件表示(inode存于内存上),但它并不会占据磁盘空间(block),数据并不会存储到磁盘上。
有名管道限制:同一台主机上,同一个系统有权限操作管道文件的任意进程都可以通过其完成进程间通讯。
②无名管道
无名管道不存在管道文件,其借助于父子进程共享fork之前打开的文件描述符。(文件打开机制)其数据存储在内存中。
无名管道限制:只能使用于父子进程之间(无法跨越父子关系)
管道的使用
①有名管道的使用
1、创建管道文件
命令:mkfifo 文件名
函数:int mkfifo(const char* pathname , int mode);
2、打开管道文件
int open();同文件操作中open的使用。
仅仅打开文件,如果不存在,则无法创建。
参数有两个:
参数一:打开管道文件的路径+名称
参数二:打开文件方式
注意!!!!在仅仅一端打开时,open会阻塞,只到有读端、有写端,open才会返回。
读和写的次数无必然联系。
3、写操作
int write();同文件操作中write的使用。
4、读操作
int read();同文件操作中read的使用。
注意:读写操作也会阻塞↓
read阻塞:管道中无数据。
返回条件:管道中有数据/所有的写端关闭
write阻塞:管道缓存区满。
返回条件:管道中有空间/所有的读端关闭
5、关闭
Int close();同文件操作中close的使用。
例题练习:A进程接收用户输入,B进程统计用户输入字节的个数。
代码展示:
maina.c
mainb.c
结果:
②无名管道的使用
创建并且打开无名管道(自带open过程)
int pipe(int fds[2]);
fds[2]初始时同时打开,fd[0]管道读端, fd[1]管道写端
Fork();//注意:一定要在fork之前打开pipe
父子进程均可读可写
如果父-->子进程,则父进程关闭读端,子进程关闭写端
如果子-->父进程,则子进程关闭读端,父进程关闭写端
读端判断是否通讯完成,read返回值:0
例题练习:父进程接收用户输入,子进程统计字节并且输出。
代码:
结果: