linux 无名管道pipe和有名管道FIFO

 1、管道(pipenode

管道是进程间通讯的主要手段之一。一个管道实际上就是个只存在于内存中的文件,对这个文件的操做要经过两个已经打开文件进行,它们分别表明管道的两端。管道是一种特殊的文件,它不属于某一种文件系统,而是一种独立的文件系统,有其本身的数据结构。根据管道的适用范围将其分为:无名管道和命名管道。linux

     无名管道编程

主要用于父进程与子进程之间,或者两个兄弟进程之间。在linux系统中能够经过系统调用创建起一个单向的通讯管道,且这种关系只能由父进程来创建。所以,每一个管道都是单向的,当须要双向通讯时就须要创建起两个管道。管道两端的进程均将该管道看作一个文件,一个进程负责往管道中写内容,而另外一个从管道中读取。这种传输遵循“先入先出”(FIFO)的规则。数据结构

     命名管道ide

命名管道是为了解决无名管道只能用于近亲进程之间通讯的缺陷而设计的。命名管道是创建在实际的磁盘介质或文件系统(而不是只存在于内存中)上有本身名字的文件,任何进程能够在任什么时候间经过文件名或路径名与该文件创建联系。为了实现命名管道,引入了一种新的文件类型——FIFO文件(遵循先进先出的原则)。实现一个命名管道实际上就是实现一个FIFO文件。命名管道一旦创建,以后它的读、写以及关闭操做都与普通管道彻底相同。虽然FIFO文件的inode节点在磁盘上,可是仅是一个节点而已,文件的数据仍是存在于内存缓冲页面中,和普通管道相同。函数

系统调用pipe是用来创建管道的。该调用的声明格式以下:
int pipe(int filedes[2]);
一个管道拥有两个文件描述符用来通讯,它们指向一个管道的索引节点,该调用将这两文件描述符放在参数filedes中返回。如今的许多系统中管道容许数据双向流动,但通常习惯上,文件描述符filedes[0]用来读数据,filedes[1]用来写数据。若是要求程序的可移植性好,就按照习惯的用法来编程。调用成功时,返回值为0;错误时,返回-1,并设置错误代码errno:
EMFILE:进程使用了过多的文件描述符。 
ENFILE:系统文件表满。 
EFAULT:参数filedes无效。
对于写管道: 
写入管道的数据按到达次序排列。若是管道满,则对管道的写被阻塞,直到管道的数据被读操做读取。对于写操做,若是一次write调用写的数据量小于管道容量,则写必须一次完成,即若是管道所剩余的容量不够,write被阻塞直到管道的剩余容量能够一次写完为止。若是write调用写的数据量大于管道容量,则写操做分屡次完成。若是用fcntl设置管道写端口为非阻塞方式,则管道满不会阻塞写,而只是对写返回0。
spa

 对于读管道: 
读操做按数据到达的顺序读取数据。已经被读取的数据在管道内再也不存在,这意味着数据在管道中不能重复利用。若是管道为空,且管道的写端口是打开状态,则读操做被阻塞直到有数据写入为止。一次read调用,若是管道中的数据量不够read指定的数量,则按实际的数量读取,并对read返回实际数量值。若是读端口使用fcntl设置了非阻塞方式,则当管道为空时,read调用返回0。

设计

有名管道又称为FIFO,是进程间通讯的一种方式。FIFO具备如下特色:索引

          1.全双工的通讯模式,数据先进先出;进程

          2.能够用于任意的进程之间,经过指定相同的管道文件进行通讯;

          3.文件名存在文件系统中,而管道中的内容存在于内存中。可经过open、read、write对其操做;

使用FIFO的步骤以下:

1、建立/打开一个FIFO

FIFO是一种文件类型,在Linux系统中FIFO的类型用p表示。以下所示: 

-rwxr-xr-x 1 root root 7368 2008-10-29 09:05 create_fifo 
        -rw-r--r-- 1 root root 380 2008-10-29 09:05 create_fifo.c 
        prw-r--r-- 1 root root 0 2009-06-12 14:18 myfifo 
        -rwxr-xr-x 1 root root 8178 2008-10-29 08:58 read_fifo 
        -rw-r--r-- 1 root root 1185 2008-10-29 09:00 read_fifo.c 
        -rwxr-xr-x 1 root root 8333 2009-06-12 14:20 write_fifo 
        -rw-r--r-- 1 root root 1139 2009-06-12 14:19 write_fifo.c

能够看到,虽然FIFO文件存在于文件系统中(可供不一样的进程打开),但FIFO中的内容都存放在内存中,因此文件大小始终为0。
因为FIFO不是普通文件,因此只能用文件IO来访问。

#include <sys/stat.h> 
        int mkfifo(const char *path, mode_t mode);

函数mkfifo用于建立一个有名管道,参数path指定要建立的FIFO的路径,mode为该管道文件的访问权限,通常用八进制数表示。

#include <sys/stat.h> 
        #include <fcntl.h> 
        int open(const char *path, int oflag, ... );

函数open经过指定路径打开一个文件,不一样的进程能够调用open打开同一个FIFO进行通讯。参考下面的代码(相关头文件省略)

#define BUF_SIZE 51          int main(int argc, char *argv[])          {                    int fd;                   ssize_t n;                   char buf[BUF_SIZE];                   if ( argc <2)                   {                            fprintf(stdout, “Usage: %s <fifo_path>\n”, argv[0]);                            exit(1);                   }                   if ( mkfifo(argv[1], 0666) < 0 ) // 建立FIFO失败                   {                            if (errno != EEXIST ) // 出错缘由不是由于管道已存在                            {                            fprintf(stderr, “mkfifo() failed %s\n”, strerror(errno));                            exit(-1);                            }                   }                   if ( (fd = open(argv[1], O_RDWR)) < 0 ) // 打开FIFO出错                   { // 注:< 优先级要高于 =                            fprintf(stderr, “open() failed %s\n”, strerror(errno));                            exit(-1);                   }                    …                    return 0;         }

相关文章
相关标签/搜索