博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
有名管道(FIFO)
阅读量:2290 次
发布时间:2019-05-09

本文共 2951 字,大约阅读时间需要 9 分钟。

单项(半双工)数据流

mkfifo函数 

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/

你可能感兴趣的文章
Linux的命令入门
查看>>
机器学习_算法_AdaBoost
查看>>
机器学习_算法_KNN
查看>>
Deep Learning_main
查看>>
Deep Learning_mnist background introduction
查看>>
linux_shell_util
查看>>
Project manage_maven3安装,配置
查看>>
linux_ramdisk妙用
查看>>
project manage_maven_android
查看>>
Foreign Language_english_补语
查看>>
Foreign Language_english_感叹句
查看>>
Foreign Language_english_限定词
查看>>
Foreign Language_english_人称代词&数词
查看>>
Foreign Language_english_从句
查看>>
Foreign Language_english_副词和形容词区别
查看>>
Foreign Language_english_语法分析_1
查看>>
Machine Learning_mahout_20news_caution
查看>>
R_bioinfomatics_heatmap
查看>>
8086_proteus_masm配置
查看>>
8086_proteus_all_dsn
查看>>