管道可分为无名管道(Pipe)及有名管道(FIFO):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信。
管道具有以下特点:
(1)管道是半双工的,数据只能向一个方向流动;需要双方通信时,需要建立起两个管道。
(2)只能用于父子进程或者兄弟进程之间(具有亲缘关系的进程)。
(3)单独构成一个独立的文件系统。管道对于管道两端的进程而言,就是一个文件,但它不是普通的文件,不属于某种文件系统,而是自立门户,单独构成一种文件系统,并且存在于内存中。
(4)数据的读出和写入:一个进程向管道中写的内容被管道另一端的进程读出。写入的内容每次都添加在管道缓冲区的末尾,并且每次都是从缓冲区的头部读出数据。
如何使用无名管道通信呢?
首先必须用pipe函数建立管道
Pipe函数:
表头文件:#include <unistd.h>
定义函数:int pipe(int filedes[2]);
函数说明:pipe()会建立管道,并将文件描述符有参数filedes数组返回,filedes[0]为管道的读取端,filedes[1]则为管道的写入端。
返回值:若成功则返回0,否则返回-1.
代码举例:my_pipe.c
管道用于不同进程间通信,通常先创建一个管道,在通过fork函数创建一个子进程,该子进程会继承父进程所建的管道。
注:必须在系统调用fork()前调用pipe(),否则子进程将不会继承文件描述符。
读写无名管道
一般文件的I/O函数都可以用于管道,如close、read、write等等
从管道中读数据:
(1)如果管道的写端不存在,则认为已经读到了数据的末尾,读函数返回的字节数为0.
(2)当管道的写端存在时,如果请求的字节数目大于PIPE_BUF,则返回管道中现有的字节数;如果请求的字节数目不大于PIPE_BUF,则返回管道中现有的数据字节数(此时管道中数据量小于请求的数据量)或者返回请求的字节数(此时,管道中的数据量不小于请求的数据量)。
有名管道:
FIFO不同于管道之处在于它提供了一个路径名与之相关联,以FIFO的文件形式存在于文件系统中。这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO 相互通信。值得注意的是,FIFO严格遵循先进先出,对管道及FIFO的读总是从开始处返回数据的,对它们的写则把数据添加到末尾,它们不支持诸如lseek()等文件定位操作。
mkfifo函数用于建立有名管道:
表头文件:#include <sys/types.h>
#include <sys/stat.h>
定义函数:int mkfifo(const char *pathname,mode_t mode);
Mkfifo()会依据参数pathname建立特殊的FIFO文件,该文件必须不存在,而参数mode为该文件的权限