管道和消息队列本质都差不多,都是linux内核的缓冲区。
管道限制
管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道
只能用于具有共同祖先的进程(具有亲缘关系的进程)之间进行通信;通常,一个管道由一个进程创建,然后该进程调用fork,此后父、子进程之间就可应用该管道。管道用的是越来越少了
管道读写规
当没有数据可读时
read调用阻塞,即进程暂停执行,一直等到有数据来到为止。
如果设置了不等待,read调用返回-1,errno值为EAGAIN。
当管道满的时候
write调用阻塞,直到有进程读走数据
如果设置了不等待,调用返回-1,errno值为EAGAIN
当管道不停的被写,写满的时候
write调用阻塞
调用返回-1,errno值为EAGAIN
如果所有管道写端对应的文件描述符被关闭,则read返回
如果所有管道读端对应的文件描述符被关闭,则write操作会产生信号SIGPIPE
当要写入的数据量不大于PIPE_BUF时,linux将保证写入的原子性。
当要写入的数据量大于PIPE_BUF时,linux将不再保证写入的原子性。
管道本质,内核中固定大小的缓冲区。
Shell脚本中的|命令本质上就是用管道技术实现的。
首先 会创建一个管道,然后有几个命令就会创建几个进程
对于执行第一个命令的进程,会关闭进程的读端,然后使用dup2命令,将标管道的写端复制成为标准输出,然后执行exec函数族,这样就相当于是对管道进行了写。对于执行第二个命令的进程,
会关闭写端,然后使用dup2命令,将管道的读端复制成为标准输出,然后执行exec函数组命令,这样第一个命令的输出就相当于是第二个命令的输入,后面多余命令都是类似的。
命名管道
管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信。
如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道。命名管道是一种特殊类型的文件。
创建一个命名管道
命名管道可以从命令行上创建,命令行方法是使用下面这个命令:mkfifo filename
命名管道也可以从程序里创建,相关函数有: int mkfifo(const char *filename,mode_t );
原文地址:https://www.cnblogs.com/randyniu/p/9180627.html