[linux]进程间通信-管道pipe的实际用法(写入/读取)

一、需求

现有两个进程A和B,B进程含较为独立且复杂的业务逻辑,A进程为主控进程,现A进程需要控制B进程执行对应的功能,且要保持响应及时。

二、分析

典型进程间通信案例,因此使用linux下的管道方法(pipe)。由于是无父子关系的两个进程的通信,因此使用命名管道,如是具有父子关系的进程,使用匿名管道。

三、操作

3.1管道初始化

        // 创建管道文件
        mkfifo(PIPE_NAME, 0777);

其中,参数1为需要创建的管道文件路径与名称,参数2为文件权限。

3.2管道打开

        fd = open(PIPE_NAME, O_WRONLY);
        // 打开管道文件
        if (fd < 0)
        {
            printf("pipein: exit{open file failed}\n");
            perror("open");
            exit(1);
        }

注意,此时处于管道的输入进程(pipein),即A进程,此时如B进程还未启动,则程序会阻塞在open函数中,等待B进程打开管道。(重点:pipe管道在open中的现象为卡住、阻塞住)

仅在A进程中打开管道的现象:

当B进程启动后打开管道后的现象:

可以看到管道顺利流通。

也因此,为避免阻塞A进程的其他功能,会使用fork()创建子进程来进入阻塞等待B进程启动完成。

3.3管道写入

            // 写入数据
            printf("pipein: write msg=%d\n", time);
            sprintf(buffer, "%d\n", time);
            write(fd, buffer, sizeof(buffer));
    
            sleep(1);

同写文件操作一致。

3.4管道读取

            // 读取数据
            read(fd, buffer, sizeof(buffer));
            printf("pipeout: read msg=%s", buffer);
    
            sleep(1);

3.5管道释放

        // 删除管道文件
        unlink(PIPE_NAME);

如不执行删除操作,管道文件会一直存在,且可以被继续使用。

四、源码

4.1 pipein.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    #define BUFFER_SIZE 256
    #define PIPE_NAME "/mnt/UDISK/q2j"
    
    int main()
    {
        int fd;
        char buffer[BUFFER_SIZE];
        pid_t pid;
    
        // 创建管道文件
        mkfifo(PIPE_NAME, 0777);
    
        printf("pipein: create mkfifo successed\n");
        fd = open(PIPE_NAME, O_WRONLY);
        // 打开管道文件
        if (fd < 0)
        {
            printf("pipein: exit{open file failed}\n");
            perror("open");
            exit(1);
        }
        printf("pipein: opening pipe\n");
        int time = 0;
        while (1)
        {
            time++;
    
            // 写入数据
            printf("pipein: write msg=%d\n", time);
            sprintf(buffer, "%d\n", time);
            write(fd, buffer, sizeof(buffer));
    
            sleep(1);
        }
        // 关闭文件
        close(fd);
    }
    

4.2 pipeout.c

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <fcntl.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    
    #define BUFFER_SIZE 256
    #define PIPE_NAME "/mnt/UDISK/q2j"
    
    int main()
    {
        int fd;
        char buffer[BUFFER_SIZE];
        pid_t pid;
    
        printf("pipeout: init successed\n");
        // 打开管道文件
        if ((fd = open(PIPE_NAME, O_RDONLY)) < 0)
        {
            perror("open");
            exit(1);
        }
        while (1)
        {
    
            // 读取数据
            read(fd, buffer, sizeof(buffer));
            printf("pipeout: read msg=%s", buffer);
    
            sleep(1);
        }
        // 关闭文件
        close(fd);
    
        // 删除管道文件
        unlink(PIPE_NAME);
    
        return 0;
    }
    

五、总结

注意使用管道时的阻塞情况。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-19 16:00:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-19 16:00:04       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-19 16:00:04       82 阅读
  4. Python语言-面向对象

    2023-12-19 16:00:04       91 阅读

热门阅读

  1. 某知名经济开发区绩效管理体系建设纪实

    2023-12-19 16:00:04       60 阅读
  2. C#使用HtmlAgilityPack解析HTML结构

    2023-12-19 16:00:04       53 阅读
  3. 绘制动态图表 Python

    2023-12-19 16:00:04       55 阅读
  4. html懒人加载实现

    2023-12-19 16:00:04       59 阅读
  5. 自动生成请假条 - Python实现

    2023-12-19 16:00:04       67 阅读
  6. 面试记录一

    2023-12-19 16:00:04       53 阅读
  7. [hive] 在hive sql中定义变量

    2023-12-19 16:00:04       58 阅读