zoukankan      html  css  js  c++  java
  • Linux 进程间通信 有名管道(fifo)

    有名管道特点

    1)无名管道只能用于具有亲缘关系的进程之间,这就限制了无名管道的使用范围

    2)有名管道可以使互不相关的两个进程互相通信。

    3)有名管道可以通过路径名来指出,并且在文件系统中可见,但内容存放在内存中

    4)进程通过文件IO来操作有名管道

    5)有名管道遵循先进先出规则

    6)不支持如lseek() 操作

     

    注意
    以O_WRONLY打开管道,读阻塞
    以O_RDWR打开管道,当管道中没有数据,读阻塞
    //当进程用open打开有名管道用只读方式打开的话,则返回的文件描述符就代表管道的读端

    创建有名管道

      int mkfifo(const char *filename, mode_t  mode)

      参数:filename 有名管道文件名(包括路径);mode 权限(读写0666)

      成功返回 0 ,失败返回-1 并设置 errno 号 errno == EEXIST 时表示该有名管道已经存在

    对有名管道的操作是通过文件IO 中的open read write 等操作的

    例子:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    
    
    int main(int argc, const char *argv[])
    {
        char buf[50] = {0};
        if(mkfifo("./fifo",0777) != 0 ) //在当前路径下(运行程序所在的路径)创建有名管道,有名管道权限读写执行
        {
            if(errno == EEXIST) //当该有名管道存在时,提示下
            {
                printf("File exists
    ");
            }
            else
            {
                perror("mkfifo fail ");
                exit(1);
            }
        }
    
        int fd;
        fd = open("./fifo",O_RDWR);//读写方式打开,使用文件IO 操作有名管道
        if(fd < 0)
        {
            perror("open fifo fail: ");
            exit(1);
        }
        write(fd,"1234567",7);
        read(fd,buf,7);
        printf("%s
    ",buf);
        return 0;
    }

    测试:

     例子:通过有名管道让两个进程实现文件的复制

     

    (1)读取文件写入有名管道中

    /* 功能:实现在终端上输入获取文件名,读取文件内容,写到有名管道fifo中
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    int main(int argc, const char *argv[])
    {
        char buf[50] = {0};
        if(mkfifo("./fifo",0777) != 0 ) //创建有名管道
        {
            if(errno == EEXIST)
            {
                printf("File exists
    ");
            }
            else
            {
                perror("mkfifo fail ");
                exit(1);
            }
        }
        int fd_fifo,fd_file;
        fd_fifo = open("./fifo",O_WRONLY);//只写方式打开,管道描述符
        if(fd_fifo < 0)
        {
            perror("open fifo fail: ");
            exit(1);
        }
        fd_file = open(argv[1],O_RDONLY);//只读方式打开,源文件进行复制到管道中
        if(fd_file < 0)
        {
            perror("open source fail ");
            exit(1);
        }
    
        //循环读取文件内容
        ssize_t size;
        while(1)
        {
            size = read(fd_file,buf,50); //文件中读取数据,返回读取到多少数据
            if(size <= 0)
            {
                break;
            }
            write(fd_fifo,buf,size);
        }
        close(fd_file);//关闭读的源文件
        close(fd_fifo);
        return 0;
    }

    (2)读取有名管道中的数据,写入文件中实现复制

    /* 功能:实现在有名管道中读取数据,写到文件中
     * */
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <errno.h>
    int main(int argc, const char *argv[])
    {
        char buf[50] = {0};
        if(mkfifo("./fifo",0777) != 0 ) //创建有名管道
        {
            if(errno == EEXIST) //有名管道存在的情况
            {
                printf("File exists
    ");
            }
            else
            {
                perror("mkfifo fail ");
                exit(1);
            }
        }
        
        int fd_fifo,fd_file;  //此处fd_r是指有名管道,在有名管道中读取数据,写到文件中
    
        fd_fifo = open("./fifo",O_RDONLY);//读方式打开
        if(fd_fifo < 0)
        {
            perror("open fifo fail: ");
            exit(1);
        }
        
        fd_file = open(argv[1],O_WRONLY|O_CREAT|O_TRUNC,0666);//把从有名管道中读取的数据,写到文件中,只读,没有创建,清空打开
        if(fd_file < 0)
        {
            perror("fd_w open fail ");
            exit(1);
        }
        //fifo 中循环读取数据,然后写到文件中
        ssize_t size;
        while(1)
        {
            size = read(fd_fifo,buf,50); //读有名管道内容,返回读取多少个数据
            if(size <= 0)
            {
                break;
            }
            write(fd_file,buf,size); //写入文件中
        }
        close(fd_fifo);
        close(fd_file);
        return 0;
    }

    测试:此时要打开两个终端让两个进程进行通信,一个执行写操作,一个执行都操作(有名管道中有数据才可以读,且管道数据内容存在内存中)

  • 相关阅读:
    layui 自定义统一监听事件(大范围)
    layui 自定义个别事件
    Django layui {{ }}冲突解决方法
    sudo apt install ...
    Field XXX in XXXX required a bean of type XXXX that could not be found
    Springboot2+bootstrap-table1.12.1+MybatisPlus3.0 后台物理分页实现
    springboot2在后台打印系统执行的SQL
    @Service注解让spring找到你的Service bean
    接受参数的包装类的数据类型写错报错
    Java 日期转字符串
  • 原文地址:https://www.cnblogs.com/electronic/p/10939770.html
Copyright © 2011-2022 走看看