Linux 进程间通信(2) -- fifo有名管道

进程间通信(IPC – InterProcess Communication)

通信的方式有很多: 文件, 管道, 信号, 共享内存, 消息队列, 套接字, 命名管道等等;

  • 但是由于设计缺陷现在常用的有:
    1.管道(简单, 默认匿名管道, 还有有名管道)
    2.信号(开销小, 但是如果不是做系统编程一般不用, 因为缺点大于有点, 比如有没有收到无法确认)
    3.共享映射区(无血缘关系之间)
    4.本地套接字(最稳定)

二、 管道(有名管道, fifo)

  • 特点: 相当于一个伪文件, 也是是用内核缓冲区, 也是队列实现, 也是只能读取一次, 对其进行读写操作时也是阻塞
  • 使用场景: 弥补pipe, 可以完成无血缘关系的进程间通信.
  • 创建方式:
    1. 命令 mkfifo 文件名; 该文件不管怎么对其操作, 都不会改变其大小, 一直是0;
    2. 通过 int mkfifo(const char *pathname, mode_t mode); 在第三章, 使用命令: man 3 mkfifo查看
  • 使用: 即当成普通文件进行操作, open/close, read/write, unlink; 但是不能使用lseek对读写指针进行操作, 因为破坏了fifo规则
    1. 创建 a.c和b.c, 以及fifo文件
    2. a.c中 open — 读方式打开, 进行读操作, 然后关闭
    3. b.c中open — 写方式打开, 进行写操作, 然后关闭
  • 示例代码:
    写端程序代码:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, const char* argv[])
{
    if(argc < 2)
    {
        printf("./a.out fifoname\n");
        exit(1);
    }

    // 判断文件是否存在
    int ret = access(argv[1], F_OK);
    if(ret == -1)
    {
        int r = mkfifo(argv[1], 0664);
        if(r == -1)
        {
            perror("mkfifo error");
            exit(1);
        }
        printf("有名管道%s创建成功\n", argv[1]);
    }

    int fd = open(argv[1], O_WRONLY);
    if(fd == -1)
    {
        perror("open error");
        exit(1);
    }
    
    char *p = "hello, world";
    while(1)
    {
        sleep(1);
        int len = write(fd, p, strlen(p)+1);
    }

    close(fd);
    
    return 0;
}

读端程序代码:

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>

int main(int argc, const char* argv[])
{
    if(argc < 2)
    {
        printf("./a.out fifoname\n");
        exit(1);
    }

    // 判断文件是否存在
    int ret = access(argv[1], F_OK);
    if(ret == -1)
    {
        int r = mkfifo(argv[1], 0664);
        if(r == -1)
        {
            perror("mkfifo error");
            exit(1);
        }
        printf("有名管道%s创建成功\n", argv[1]);
    }

    int fd = open(argv[1], O_RDWR);
    if(fd == -1)
    {
        perror("open error");
        exit(1);
    }
    
    char buf[512];
    while(1)
    {
        int len = read(fd, buf, sizeof(buf));
        buf[len] = 0;
        printf("buf = %s\n, len = %d", buf, len);//在此打印len证明该管道也是阻塞的
    }

    close(fd);
    
    return 0;
}

    原文作者:dab61956e53d
    原文地址: https://www.jianshu.com/p/2c7ca7625e1d
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞