进程间通信——命名管道

   前面介绍的管道属于匿名管道,只能够用于有血缘关系的进程间通信,比如父子进程之间的通信。下面主要讨论另一种管道——命名管道。

    在命名管道(named pipe或FIFO)提出后,该限制得到了克服。FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存储于文件系统中。命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够通过FIFO相互通信。同时,FIFO(first input first output)总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出。


【命名管道的创建和读写】

     命名管道的创建有两种方式:一是Shell下交互一个命名管道;二是在程序中使用系统函数建立命名管道。

    Shell方式下创建命名管道的系统函数有两个:mknod和mkfifo

头文件:                                                                                                          头文件:

       #incldue<sys/types.h>                                                                                     #incldue<sys/types.h>

       #include<sys/stat.h>                                                                                        #include<sys/stat.h>

       #include<fcntl.h>                                                                                                         

       int mknod(const char* path,mode_t mod,dev_t dev);                                     int mkfifo(const char* path,mode_t mode);

       这两个函数调用成功都返回0,失败都返回-1.

       mknod和mkfifo这两个函数都能创建一个FIFO文件,注意是创建一个真实存在于文件系统中的文件,path指定了文件名,而mode为创建的命名管道的模式,则指定了文件的读写权限。dev为设备值,该值取决于文件创建的种类,它只在创建设备文件时才会用到。

       mkfifo函数的作用是在文件系统中创建一个文件,该文件用于提供FIFO功能,即命名管道。 前边讲的那些管道都没有名字,因此它们被称为匿名管道,或简称管道。对文件系统来说, 匿名管道是不可见的,它的作用仅限于在父进程和子进程两个进程间进行通信。而命名管道是一个可见的文件,因此,它可以用于任何两个进程之间的通信,不管这两个进程是不 是父子进程,也不管这两个进程之间有没有关系。


例:下面实现两个进程通过命名管道进行通信:

                     

运行结果:

read端:                                                                                                                                              write端:

                                                                                


      其中,read端中的“0666|S_IFIFO”指明创建一个命名管道且存取权限为0666,即就是创建者、与创建者同组的用户、其他用户对该命名管道的访问权限都是读和写。 命名管道创建后就可以使用了,其使用方法和管道基本是相同的。只是使用命名管道时,必须先调用open()函数将其打开。因为命名管道是存储于内存中的特殊文件。调用open()打开命名管道的进程可能会被阻塞,但如果同时用读写方式 (O_RDWR)打开,则一定不会导致阻塞;如果以只读方式(O_RDONLY)打开,则调用open()函数的进程将会被阻塞直到有写入数据的一方打开管道;同样以写方式(O_WRONLY)打开 也会阻塞直到有读取数据的一方打开管道。


【管道的实现机制和管道的容量】

      管道在进程间通信中是比较常用的,其实管道就是一种特殊的文件。

      (1)管道的大小

              管道是一个固定大小的缓冲区。Linux中该缓冲区的大小为1页,即4K字节,所以在写管道时可能变满,当这种情况发生时,随后对管道write()调用将默认地被阻塞,等待某些数据被读取,以便腾出足够的空间供write()调用写。

      (2)读进程工作较写进程快

               当所有当前进程数据已被读取时,管道变空。当这种情况发生时,一个随后的read()调用将默认地被阻塞,等待某些数据被写入,这解决了read()调用返回文件结束的问题。

       (3)管道读数据是一次性的

               数据一旦被读,就会从管道中被抛弃,释放空间以便写更多的数据。


例:查看管道容量


运行结果:






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章