进程间通信_03命名管道

一 为什么会有命名管道

匿名管道的产生攻克了有亲缘关系的进程之间的小量传输数据,可是匿名管道却不能在没有亲缘关系的进程之间进行传输数据。

为了解决问题,就出现了命名管道。

命名管道也是在内核分配了一块存储区,而且用一个文件名称与之关联,以FIFO(First In First Out)的文件形式存放于文件系统之中。

这样其它不相关的进程仅仅要知道管道的名称也能訪问管道。

二 和匿名管道在使用上的差别

和匿名管道的唯一差别在于管道的创建和打开方式的不同,其它操作方式全然一致。

创建的时候:命名管道用mkfifo函数,打开的时候命名管道open函数

匿名管道,创建和打开用pipe函数一步实现。

三 命名管道的操作

匿名管道的操作和文件的操作类似,能够当成一个特殊的文件

与普通文件唯一的不同就是,创建的时候普通文件用create()函数或者open()函数创建

                                                                匿名管道用mkfifo创建

四 命名管道的创建

方式一:手动创建

$ mkfifo filename

方式二:代码创建

#include <sys/types.h>
#include <sys/stat.h>
int mkfifo(const char * pathname,     //带路径的管道名称
                  mode_t mode)        //管道的操作权限
//返回值:0 (成功),-1(打开失败,错误码见errno)

mode參数取值:S_I(R/W/X)(USR/GRP/OTH) 、S_IRWX(U/G/O)

当中,R/W/X分别表示读/写/运行权限,

USR/GRP/OTH分别表示文件全部者/文件所属组/其它用户

S_IRWXU =  S_IRUSR | S_IWUSR | S_IXUSR

S_IRWXG =  S_IRGRP | S_IWGRP | S_IXGRP

S_IRWXO =  S_IROTH | S_IWOTH | S_IXOTH

比方, S_IRUSR表示文件全部者有读权限;

S_IWUSR表示文件全部者有写权限;

多个值用‘|‘连接,比方S_IRUSR|S_IWUSR表示文件全部者有读写权限

上面的取值能够也能够直接用八进制为的数字取代,如:00600 表示 文件全部者有读写权限

五 命名管道的打开

负责写命名管道的进程已仅仅写的形式打开命名管道,负责读命名管道的进程已仅仅读的形式打开命名管道。

命名管道的读端 和 写端 都连上才算打开命名管道成功,否则,进程会堵塞在open函数(没有设置不堵塞标志的情况下)。

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
int open(const char* pathname,     //带路径的管道名称
                int flags          //管道打开的方式
                ...);              //其它參数,比方,在创建的时候能够赋权限,这里由于是由mkfifo创建,所以忽略
//返回值:>2 (返回管道的描写叙述符),-1(打开失败,错误码见errno)

flags參数取值

   O_RDONLY 以仅仅读方式打开文件   

O_WRONLY 以仅仅写方式打开文件

O_RDWR 以可读写方式打开文件。   

上述三种旗标是相互排斥的,仅仅能取一个,可与下列选项或运算组合(|)使用。

O_CREAT             若欲打开的文件不存在则自己主动建立该文件。   

O_EXCL                一般和O_CREAT一起使用,设置之后在创建文件时发现文件已经存在的话就报错。  

O_NONBLOCK     以不可阻断的方式打开文件,也就是不管有无数据读取或等待,都会马上返回进程之中。  

O_TRUNC             若文件存在而且以可写的方式打开时,清空文件里的内容。

O_APPEND          在写数据时将文件光标移到文件尾部。

O_SYNC               以同步的方式打开文件。

O_NOCTTY           假设欲打开的文件为终端机设备时,则不会将该终端机当成进程控制终端机。     

O_NOFOLLOW     假设參数pathname 所指的文件为一符号连接,则会令打开文件失败。   

O_DIRECTORY     假设參数pathname 所指的文件并不是为一文件夹,则会令打开文件失败。

六 使用实例

/************************************************************************************
    > File Name: testfifo.c
    > Author: qiaozp
    > Mail: [email protected]
    > Created Time: 2014-9-17 14:29:35
    > Step: 1 调用mkfifo函数创建一个命名管道
            2 在写端进程 用open函数以O_WRONLY的方式连接管道,并用write函数读取数据
            3 在读端进程 用open函数以O_RDONLY的方式连接管道,并用read函数读取数据
 ************************************************************************************/
#include <errno.h>
#include <fcntl.h>
#include <string.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
using namespace std;

#define  BUFF_LEN 100
#define PIPE_NAME "./PipeOne"

int main(int argc, char** argv)
{
    if (argc != 2)
    {
        cout << "请在后面加上參数[r/w], r表示读管道;w表示写管道。" << endl;
        return -1;
    }

    //创建管道
    if ((mkfifo(PIPE_NAME, S_IRWXU) == -1) && (errno != EEXIST))
    {
        cout << "创建管道[" << PIPE_NAME << "]失败,错误信息[" << strerror(errno) << "]." << endl;
        return -1;
    }

    int fd;
    char buff[BUFF_LEN];
    if (strncasecmp(argv[1], "w", 1) == 0)
    {
        //写管道的进程
        if ((fd = open(PIPE_NAME, O_WRONLY)) == -1)
        {
            cout << "连接管道[" << PIPE_NAME << "]失败,错误信息[" << strerror(errno) << "]." << endl;
            return -1;
        }

        do
        {
            cout << "请输入须要从管道传输的数据: ";
            memset(buff, 0, BUFF_LEN);
            scanf("%s", buff);
            write(fd, buff, sizeof(buff));
        } while (strncasecmp(buff, "end", 3) != 0);
    }
    else if (strncasecmp(argv[1], "r", 1) == 0)
    {
        //读管道的进程
        if ((fd = open(PIPE_NAME, O_RDONLY)) == -1)
        {
            cout << "连接管道[" << PIPE_NAME << "]失败,错误信息[" << strerror(errno) << "]." << endl;
            return -1;
        }
        do
        {
            memset(buff, 0, BUFF_LEN);
            read(fd, buff, sizeof(buff));
            cout << "从管道读取到的数据为: " << buff << endl;
        } while (strncasecmp(buff, "end", 3) != 0);
    }
    else
    {
        cout << "请在后面加上正确的參数[r/w], r表示读管道;w表示写管道。" << endl;
    }
    return 0;
}
时间: 2024-08-03 15:24:28

进程间通信_03命名管道的相关文章

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

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

进程间通信:命名管道

一.命名管道(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的创建进程之间),因此,

进程间通信之命名管道

命名管道(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通道. 对文件系统来说,匿名管道(管道)是不可见的,它的作用仅限于在父进程和子进程两个进程间进行通信.而命名管道是一个可见的文件,因此,他可以用于任意两个进程间进行通信,不管这两个进程是不是父子进程,也不管这两

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

在前面,介绍了一种进程间的通信方式:使用信号,我们创建通知事件,并通过它引起响应,但传递的信息只是一个信号值.这里将介绍另一种进程间通信的方式——匿名管道,通过它进程间可以交换更多有用的数据. 一.什么是管道 如果你使用过Linux的命令,那么对于管道这个名词你一定不会感觉到陌生,因为我们通常通过符号“|"来使用管道,但是管理的真正定义是什么呢?管道是一个进程连接数据流到另一个进程的通道,它通常是用作把一个进程的输出通过管道连接到另一个进程的输入. 举个例子,在shell中输入命令:ls -l