本文共 2951 字,大约阅读时间需要 9 分钟。
单项(半双工)数据流
mkfifo函数的作用是在文件系统中创建一个文件,该文件用于提供FIFO功能,即命名管道。前边讲的那些管道都没有名字,因此它们被称为匿名管道,或简称管道。对文件系统来说,匿名管道是不可见的,它的作用仅限于在父进程和子进程两个进程间进行通信。而命名管道是一个可见的文件,因此,它可以用于任何两个进程之间的通信,不管这两个进程是不是父子进程,也不管这两个进程之间有没有关系。Mkfifo函数的原型如下所示:
#include#include int mkfifo( const char *pathname, mode_t mode );
mkfifo函数需要两个参数,第一个参数(pathname)是将要在文件系统中创建的一个专用文件。第二个参数(mode)用来规定FIFO的读写权限。Mkfifo函数如果调用成功的话,返回值为0;如果调用失败返回值为-1。下面我们以一个实例来说明如何使用mkfifo函数建一个fifo,具体代码如下所示:
int ret;...ret = mkfifo( "/tmp/cmd_pipe", S_IFIFO | 0666 );if (ret == 0) ...{ // 成功建立命名管道} else ...{ // 创建命名管道失败}
在这个例子中,利用/tmp目录中的cmd_pipe文件建立了一个命名管道(即fifo)。之后,就可以打开这个文件进行读写操作,并以此进行通信了。命名管道一旦打开,就可以利用典型的输入输出函数从中读取内容。举例来说,下面的代码段向我们展示了如何通过fgets函数来从管道中读取内容:
pfp = fopen( "/tmp/cmd_pipe", "r" ); ...ret = fgets( buffer, MAX_LINE, pfp );我们还能向管道中写入内容,下面的代码段向我们展示了利用fprintf函数向管道写入的具体方法:
pfp = fopen( "/tmp/cmd_pipe", "w+ ); ...ret = fprintf( pfp, "Here’s a test string!\n" );
对命名管道来说,除非写入方主动打开管道的读取端,否则读取方是无法打开命名管道的。Open调用执行后,读取方将被锁住,直到写入方出现为止。尽管命名管道有这样的局限性,但它仍不失为一种有效的进程间通信工具。
上面介绍的是与管道有关的一些系统调用,下面介绍管道命令相关的系统命令。 与管道相关的系统命令 现在开始,我们来研究与进程间通信密切相关的一些系统命令。首先介绍的是mkfifo命令,它的功能与mkfifo系统调用相似,只不过它是用来在命令行中建立一个命名管道。 在命令行下建立fifo的专用文件,即命名管道的常用方法有两个,mkfifo命令便是其中之一。mkfifo命令的一般用法如下所示:mkfifo [options] name
这里的options一般为-m,即模式,用以指出读写权限;name是要创建的管道的名称,必要时可以加上路径。如果我们没有规定权限,该命令会采取默认值0644。这里以一个具体实例来说明如何在/tmp目录下面建立一个称为cmd_pipe的命名管道:
$ mkfifo /tmp/cmd_pipe
下面用例子说明如何给命名管道指定读写权限。这里我们先将前面建立的管道删掉,然后重新建立管道,并指定管道的权限为0644,当然您也可以指定其他权限:
$ rm cmd_pipe$ mkfifo -m 0644 /tmp/cmd_pipe
上面的权限一经建立,就能够在命令行行下通过此管道进行通信了。比如,可以在一个终端上,利用cat命令来读取管道:
$ cat cmd_pipe
当输入该命令后,我们的进程就会被挂起,等待写入程序打开此管道。现在,在另一个终端上利用echo命令向这个命名管道写入:
$ echo Hi > cmd_pipe
这个命令结束后,要读取该管道的程序(即cat)将被唤醒,然后结束。为醒目起见,这里列出完整的读取方(也就是读取管道的程序)输入的命令和得到的结果:
$ cat cmd_pipeHi$
由此看来,命名管道不仅在C程序中非常有用,而且在脚本中作用也很大。当然,如果组合使用,效果也是很好的。
除了mkfifo命令外,mknod命令也可以用来创建命名管道,其用法如下所示:$ mknod cmd_pipe p
该命令执行后,将在当前目录下创建一个命名管道cmd_pipe,p用于指出建立的是命名管道。
#include "unpipc.h"#define FIFO1 "/tmp/fifo.1"#define FIFO2 "/tmp/fifo.2"void client(int,int) ,server(int,int);int main(int argc,char **argv){ int readfd,writefd; pid_t childpid; /* create two FIFOs;OK if they already exist */ if((mkfifo(FIFO1,FILE_MODE)<0) && (errno != EEXIST)) err_sys("can't create %s",FIFO1); if((mkfifo(FIFO2,FILE_MODE)<0) && (errno != EEXIST)){ unlink(FIFO1); err_sys("can't create %s",FIFO2); } if((childpid = Fork()) == 0){ readfd = Open(FIFO1,O_RDONLY, 0); writefd = Open(FIFO2,O_WRONLY, 0); server(readfd, writefd); exit(0); } /* parent */ writefd = Open(FIFO1, O_WRONLY, 0); readfd = Open(FIFO2, O_RDONLY, 0); client(readfd,writefd); Waitpid(childpid, NULL, 0);/* wait for child to terminate */ Close(readfd); close(writefd); Unlink(FIFO1); Unlink(FIFO2); exit(0);}
转载地址:http://efbnb.baihongyu.com/