zoukankan      html  css  js  c++  java
  • 进程间通信_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: qiaozongpeng@163.com 
        > 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;
    }





  • 相关阅读:
    python web 开发中的csrf_token问题及处理方法
    开源编辑器ueditor
    表格中的文字超出长度隐藏,显示省略号
    django前端渲染多对多关系(比如一本书的作者有哪些)
    轻量级分布式 RPC 框架
    大杀器TheFatRat
    WEB扫描器Atscan的安装和使用
    Python类(二)-类的继承
    南京邮电大学网络攻防平台WEB题
    PHP文件操作(三)-文件的写入
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/4379109.html
Copyright © 2011-2022 走看看