进程间通信二(命名管道)

在前一篇文章中,我们看到了如何使用匿名管道来在进程之间传递数据,这个方式有一个缺陷,就是这些进程必须由一个共同的祖先进程启动,这在不相关的的进程之间交换数据带来了不便。而另一种通信方式——命名管道,可以解决不相关进程间的通信问题。

1.什么是命名管道?
命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和之前所讲的没有名字的管道(匿名管道)类似。

由于Linux中所有的事物都可被视为文件,所以对命名管道的使用也就变得与文件操作非常的统一,也使它的使用非常方便,同时我们也可以像平常的文件名一样在命令中使用。

2.如何创建命名管道?
#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char *filename, mode_t mode);

若成功则返回0,否则返回-1,错误原因存于errno中。
这个函数创建一个FIFO文件,注意是创建一个真实存在于文件系统中的文件,filename指定了文件名,而mode则指定了文件的读写权限。

3.访问命名管道

3.1 打开FIFO文件
与打开其他文件一样,FIFO文件也可以使用open调用来打开。注意,mkfifo函数只是创建一个FIFO文件,要使用命名管道还是将其打开。

但是有两点要注意,1、就是程序不能以O_RDWR模式打开FIFO文件进行读写操作,而其行为也未明确定义,因为如一个管道以读/写方式打开,进程就会读回自己的输出,同时我们通常使用FIFO只是为了单向的数据传递。2、就是传递给open调用的是FIFO的路径名,而不是正常的文件。

打开FIFO文件通常有四种方式,
[cpp] view plain copy print?
open(const char *path, O_RDONLY);//1
open(const char *path, O_RDONLY | O_NONBLOCK);//2
open(const char *path, O_WRONLY);//3
open(const char *path, O_WRONLY | O_NONBLOCK);//4
在open函数的调用的第二个参数中,你看到一个陌生的选项O_NONBLOCK,选项O_NONBLOCK表示非阻塞,加上这个选项后,表示open调用是非阻塞的,如果没有这个选项,则表示open调用是阻塞的。

open调用的阻塞是什么一回事呢?很简单,对于以只读方式(O_RDONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_RDONLY),除非有一个进程以写方式打开同一个FIFO,否则它不会返回;如果open调用是非阻塞的的(即第二个参数为O_RDONLY | O_NONBLOCK),则即使没有其他进程以写方式打开同一个FIFO文件,open调用将成功并立即返回。

对于以只写方式(O_WRONLY)打开的FIFO文件,如果open调用是阻塞的(即第二个参数为O_WRONLY),open调用将被阻塞,直到有一个进程以只读方式打开同一个FIFO文件为止;如果open调用是非阻塞的(即第二个参数为O_WRONLY | O_NONBLOCK),open总会立即返回,但如果没有其他进程以只读方式打开同一个FIFO文件,open调用将返回-1,并且FIFO也不会被打开。

4. 实例

//fifo_read.c

include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO "/tmp/myfifo"
main(int argc,char** argv)
{
  char buf_r[100];
  int fd;
  int nread;
  if((mkfifo(FIFO,O_CREAT|O_EXCL)<0)&&(errno!=EEXIST))
  printf("cannot create fifoserver\n");
  printf("Preparing for reading bytes....\n");
  memset(buf_r,0,sizeof(buf_r));
  fd=open(FIFO,O_RDONLY|O_NONBLOCK,0);
  if(fd==-1)
  {
    perror("open");
    exit(1);
  }
  while(1)

  {
    memset(buf_r,0,sizeof(buf_r));
    if((nread=read(fd,buf_r,100))==-1)

    {
      if(errno==EAGAIN)
      printf("no data yet\n");
    }
    printf("read %s from FIFO\n",buf_r);
    sleep(1);
  }
  pause();
  unlink(FIFO);
}

//fifo_write.c

#include<sys/types.h>
#include<sys/stat.h>
#include<errno.h>
#include<fcntl.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define FIFO_SERVER "/tmp/myfifo"
main(int argc,char** argv)
{
  int fd;
  int nwrite;
  char w_buf[100];
  for(;;)
  {
    memset(&w_buf, 0, sizeof(w_buf));
    fd=open(FIFO_SERVER,O_WRONLY|O_NONBLOCK,0);
    printf("please input your data:\n");
    scanf("%s", w_buf);
    if((nwrite=write(fd,w_buf,100))==-1)
    {
      if(errno==EAGAIN)
      printf("The FIFO has not been read yet. Please try later\n");
    }
    else
      printf("write %s to the FIFO\n",w_buf);
  }
}

4.1程序的编译

[[email protected] fifo]$ls
fifo_read.c fifo_write.c
[[email protected] fifo]$gcc fifo_read.c -o read
[[email protected] fifo]$gcc fifo_write.c -o write
[[email protected] fifo]$ls
fifo_read.c fifo_write.c read write
[[email protected] fifo]$

程序的运行

在当前console 1中运行read,在console2中运行write

[[email protected] fifo]$sudo ./read
Preparing for reading bytes....
read from FIFO
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
read Hello from FIFO
read FIFO from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
no data yet
read from FIFO
^C[[email protected] fifo]$

console2

[[email protected] fifo]$./write
please input your data:
Hello fifo!
write Hello to the FIFO
please input your data:
write fifo! to the FIFO
please input your data:
^C
[[email protected] fifo]$./write
please input your data:
Hello FIFO
write Hello to the FIFO
please input your data:
write FIFO to the FIFO
please input your data:
^C
[[email protected] fifo]$

时间: 2024-11-08 18:58:57

进程间通信二(命名管道)的相关文章

简述Linux进程间通信之命名管道FIFO

上文聊到管道(pipe),可以使有亲缘关系的进程间进行通信. 对于没有亲缘关系的进程如何通信?本文来聊一聊命名管道FIFO. 一.概念 命名管道FIFO,提供一个路径名与之关联,以文件形式存储于文件系统中. 一个进程以r方式打开,另一个程序以w方式打开,即可在两个进程之间建立管道. 通过以fifo文件作为媒介,可以使任意两个进程通过该文件进行通信. 命名管道(fifo)特性与管道(pipe)类似,不必赘述. 下面我们看FIFO如何进行进程间通信,首先来介绍一下所用到的函数: 二.函数原型 #in

Linux环境编程之IPC进程间通信(二):管道

管道作为最古老的进程间通信方法,它有以下几个特点: 1.在所有的UNIX实现中都存在. 2.没有名字,因此只能由有亲缘关系的进程使用. 3.它由函数pipe创建,read和write函数访问,但只提供单路(单向)数据流. <span style="font-size:14px;">#include <unistd.h> int pipe(int fd[2]); 返回:若成功则为0,若出错则为-1</span> 经由参数fd返回两个文件描述符:fd[0

进程间通信:命名管道

一.命名管道(FIFO) 匿名管道应用的一个限制就是只能在具有共同祖先(具有亲缘关系)的进程间通信.如果我们想在不相关的进程之间交换数据,可以使用FIFO文件来做这项工作,它经常被称为命名管道. 命名管道可以从命令行上创建,命令行方法是使用下面这个命令:$ mkfifo filename命名管道也可以从程序里创建,相关函数有:int mkfifo(const char *filename,mode_t mode); 二.命名管道和匿名管道 匿名管道由pipe函数创建并打开.命名管道由mkfifo

Linux进程间通信 -- 使用命名管道

在前一篇文章—— Linux进程间通信 -- 使用匿名管道 中,我们看到了如何使用匿名管道来在进程之间传递数据,同时也看到了这个方式的一个缺陷,就是这些进程都由一个共同的祖先进程启动,这给我们在不相关的的进程之间交换数据带来了不方便.这里将会介绍进程的另一种通信方式——命名管道,来解决不相关进程间的通信问题. 一.什么是命名管道 命名管道也被称为FIFO文件,它是一种特殊类型的文件,它在文件系统中以文件名的形式存在,但是它的行为却和之前所讲的没有名字的管道(匿名管道)类似. 由于Linux中所有

Linux下进程间通信之命名管道(FIFO)

匿名管道的一个不足之处是没有名字,因此,只能用于具有亲缘关系的进程间通信.在命名管道(FIFO)提出后,该限制得到了克服.FIFO不同于pipe在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.命名管道是一个设备文件,因此,即使进程与创建FIFO的进程不存在亲缘关系,只要可以访问该路径,就能够相互通信. FIFO总是按照先进先出的原则工作,第一个被写入的数据将首先从管道中读出. Linux下有两种方式创建FIFO,一是在shell下交互的建立一个命名管道,二是在程序中使用系统函

进程间通信(5) - 命名管道(FIFO)

1. 前言 本篇文章的所有例子,基于RHEL6.5平台.前一篇文章介绍了匿名管道.点此链接. 2.介绍 管道应用的一个重大限制是它没有名字,因此,只能用于具有亲缘关系的进程间通信,在有名管道(named pipe或FIFO)提出后,该限制得到了克服.FIFO不同于管道之处在于它提供一个路径名与之关联,以FIFO的文件形式存在于文件系统中.这样,即使与FIFO的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过FIFO相互通信(能够访问该路径的进程以及FIFO的创建进程之间),因此,

进程间通信_03命名管道

一 为什么会有命名管道 匿名管道的产生攻克了有亲缘关系的进程之间的小量传输数据,可是匿名管道却不能在没有亲缘关系的进程之间进行传输数据. 为了解决问题,就出现了命名管道. 命名管道也是在内核分配了一块存储区,而且用一个文件名称与之关联,以FIFO(First In First Out)的文件形式存放于文件系统之中. 这样其它不相关的进程仅仅要知道管道的名称也能訪问管道. 二 和匿名管道在使用上的差别 和匿名管道的唯一差别在于管道的创建和打开方式的不同,其它操作方式全然一致. 创建的时候:命名管道

进程间通信之命名管道

命名管道(FIFO)是进程间通信的一种方式,DEMO如下: // 写进程 int main(int argc, char **argv) { char filename[] = "/tmp/my_fifo"; if (mkfifo(filename, 0777) < 0) { perror("mkfifo error"); exit(1); } int fd = open(filename, O_WRONLY); char buffer[128] = &quo

Linux系统编程——进程间通信:命名管道(FIFO)

命名管道的概述 无名管道,由于没有名字,只能用于亲缘关系的进程间通信(更多详情,请看<无名管道>).为了克服这个缺点,提出了命名管道(FIFO),也叫有名管道.FIFO 文件. 命名管道(FIFO)不同于无名管道之处在于它提供了一个路径名与之关联,以 FIFO 的文件形式存在于文件系统中,这样,即使与 FIFO 的创建进程不存在亲缘关系的进程,只要可以访问该路径,就能够彼此通过 FIFO 相互通信,因此,通过 FIFO 不相关的进程也能交换数据. 命名管道(FIFO)和无名管道(pipe)有一

进程间通信——命名管道

概念 管道一个不足之处是没有名字,因此只能用于具有亲缘关系的进程间通信,命名管道(named pipe或FIFO)解决了这一问题. FIFO提供一个路径名与之关联,以FIFO文件的形式存储于文件系统中.文件系统中路径名是全局的,各进程都可以访问,因此可以用文件系统中的路径名来标识一个IPC通道. 对文件系统来说,匿名管道(管道)是不可见的,它的作用仅限于在父进程和子进程两个进程间进行通信.而命名管道是一个可见的文件,因此,他可以用于任意两个进程间进行通信,不管这两个进程是不是父子进程,也不管这两