fifo

命名管道

FIFO常被称为命名管道, 以区分管道(pipe). 管道(pipe)只能用于"有血缘关系"的进程间. 但通过FIFO, 不相关的进程也能交换数据

FIFO是linux基础文件类型中的一种. 但FIFO文件在磁盘上没有数据块, 仅仅用来标识内核中一条通道. 各个进程可以打开这个文件进程read/write, 实际上是在读写内核通道, 这样就实现了进程间的通信

特点
  有名管道
  在磁盘上有这样一个文件
  伪文件, 在磁盘上大学为0
  在内核中有一个对应的缓冲区
  半双工的通信方式

使用场景
  没有血缘关系的进程间通信

创建方式
  命令: mkfifo管道名
  函数: int mkfifo(const char *pathname, mode_t mode);

fifo文件可以使用IO函数进行操作
  open/close
  read/write
  不能执行lseek操作

进程间通信
  两个不相干的进程, 进程A(a.c)和进程B(b.c)
  a.c:

int fd = open("mufifo", O_RDONLY);
read(fd, buf, sizeof(buf));
close(fd);

  b.c

int fd = open("myfifo", O_WRONLY);
write(fd, "Hello World", 11);
close(fd)

注意: a.c和b.c中open的文件需要打开一个fifo

实例程序

测试时要先关闭读端再关闭写端, 否则写端关闭后读端一直读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);  // 创建fifo
        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 = "haha";
    while (1) {
        //int len = write(fd, p, sizeof(p));    // 好像和编码方式有关
        int len = write(fd, p, strlen(p)+1);
        printf("write: %s\nlen = %d\n", p, len);
        sleep(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);  // 创建fifo
        if (r == -1) {
            perror("mkfifo error");
            exit(1);
        }
        printf("有名管道%s创建成功\n", argv[1]);
    }
    
    int fd = open(argv[1], O_RDONLY);
    if (fd == -1) {
        perror("open error");
        exit(1);
    }

    char buf[512];
    while (1) {
        int len = read(fd, buf, sizeof(buf));
        buf[len] = 0;
        printf("read: %s\nlen = %d\n", buf, len);
    }

    close(fd);

    return 0;
}
posted @ 2019-04-19 21:19  张飘扬  阅读(1007)  评论(0编辑  收藏  举报