Linux进程间通信 - (一) 管道

Linux进程间通信 - (一) 管道

一、概述

管道是Linux进程间通信的一种方式,它把一个程序的输出直接连接到另一程序的输入。Linux的管道主要包括两种:无名管道有名管道

无名管道

  • 只能用于具有亲缘关系的进程之间的通信(如父子进程或者兄弟进程之间)。
  • 是一个单工的通信模式,具有固定的读端和写端
    管道也可以看成一种特殊的文件,对于它的读写也可以使用普通的read()、write()等函数。但是它不属于任何文件系统,并且只存在于内存中

有名管道

  • 它可以使互不相关的两个进程实现彼此通信。

  • 该管道可以通过路径名来指出,并且在文件系统中是可见的。在建立了管道后,两个进程就可以把它当做普通文件进行读写操作,非常方便。

  • FIFO严格地遵循先进先出规则,对管道及FIFO的读写总是从开始处返回数据,对它们的写则把数据添加到末尾。有名管道不支持如lseek()等文件定位操作。

两种管道的原理如下图所示:
在这里插入图片描述

二、编程接口

无名管道

  • 无名管道是基于文件描述符的通信方式。当一个管道建立时,它会创建两个文件描述符:fd[0]fd[1]。其中

fd[0]固定用于读管道,而fd[1]固定用于写管道.

  • 管道关闭时只需要用close()函数将这两个文件描述符关闭即可。

具体形式如下图所示:
在这里插入图片描述

管道创建函数

创建管道可以通过pipe()函数来实现,语法如下:

头文件
	#include <unistd.h>
函数原型
	int pipe(int fd[]);
函数传入值
	fd:包含两个元素的整形数组,存放管道对应的文件描述符
函数返回值
	成功:0
	出错:-1
管道的读写

pipe()函数创建的管道两端处于一个进程中。由于管道主要是用于不同进程间通信,通常是先创建一个管道,再调用fork()函数创建一子进程,子进程会继承父进程所创建的管道。此时,父子进程管道的文件描述符对应的关系如下:
在这里插入图片描述

需要注意的是,无名管道是单工的工作方式,即进程要么只能读管道,要么只能写管道。父子进程虽然都拥有管道的读端和写端,但是只能使用其中一个。(例如,我们可以约定父进程读,子进程写)。这样就应该把不使用的读端或写端的文件描述符关闭。如上图所示,我们就建立以一个“父进程读,子进程写的管道”。同样的而我们也可以父进程写而子进程读。

如果,我们在父进程创建了多个子进程,那么各个子进程都会继承父进程的fd[0]和fd[1]。使用上面的方法,我们就可以建立亲缘进程间的通信渠道了。

管道读写的注意事项:

  1. 只有在管道的的读端存在时,写端才会有意义,否则,向管道写入数据的进程将收到内核传来的SIGPIPE(通常为Broken Pipe错误)。
  2. 向管道写入数据时,Linux将不保证写入的原子性,管道缓冲区只要有空间,写进程就会试图向管道写入数据。如果管道缓冲区已满,那么写操作将会一直阻塞
  3. 父子进程在运行时,他们的先后顺序并不能保证。所以我们不能保证父子进程已经关闭了相应的文件描述符,那么我们可以在相应的进程中调用sleep()函数,等待父/子进程完成相应的关文件描述操作。当然,这个是我们目前来看作的一种妥协,实际上我们可以用进程间的同步与互斥机制。

有名管道

有名管道(FIFO)的创建可以使用mkfifo()函数,该函数类似文件中的open()操作,可以指定管道的路径和访问权限(我们也可以在命令行中使用"mknod <管道名>"来创建有名管道);

在创建管道成功之后,就可以用open()read()write()等函数来进行读写操作,像操作普通文件一样。同样的我们可以通过open()函数向使用普通文件一样对管道设置相应的权限,如只读(O_RDONLY)。

  1. 对于读进程
    缺省的情况下,如果当前FIFO内没有数据,读进程将一直阻塞到有数据写入或是FIFO写端都被关闭。

  2. 对于写进程
    只要FIFO有空间,数据就可以被写入。若空间不足,写进程会阻塞,直到数据都写入为止。

mkfifo()函数语法

所需头文件
	#include <sys/types.h>
	#include <sys/stat.h>
函数原型
	int mkfifo(const char *filename,mode_t mode);
参数
	filename:要创建的管道名
	mode:管道的访问权限
函数返回值
	成功:0
	出错:-1

FIFO相关出错信息

EACESS
	参数filename所指定的目录路径无可执行的权限
EEXIST
	参数filename所指定的文件已存在
ENAMETOOLONG
	参数filename的路径名称太长
ENOENT
	参数filename包含的文件不存在
ENOTDIR
	参数filename中的目录存在但却非真正的目录
ENOSPC
	文件系统剩余空间不足
EROFS
	参数filename指定的文件存在于只读文件系统内
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值