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

2023-12-18 22:42:22

一、需求

现有两个进程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;
    }
    

五、总结

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

文章来源:https://blog.csdn.net/qq_34217861/article/details/135062914
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。