Linux进程 进程间通信 ---- 命名管道(FIFO文件/name pipe)(1)

命名管道出现的背景:
    命名管道(FIFO文件/name pipe),之前提到的管道,虽然能够实现进程间的通信,但是局限性也很明显。首先,这个管道只能在具有血缘关系的进程之间通信;第二,他只能实现一个进程写,一个进程读,而如果需要两者同时进行时,就得重新打开一个管道。
    为了使任意两个进程之间能够通信,就提出了命名管道


命名管道的特点:
    1、与管道的区别:提供了一个路径名与之关联,以FIFO文件的形式存储于文件系统中,能够实现任何两个进程之间通信。而匿名管道对于文件系统是不可见的,它仅限于在父子进程之间的通信。
    2、FIFO是一个设备文件,在文件系统中以文件名的形式存在,因此即使进程与创建FIFO的进程不存在血缘关系也依然可以通信,前提是可以访问该路径。
    3、FIFO(first input first output)总是遵循先进先出的原则,即第一个进来的数据会第一个被读走。


创建管道的函数原型:
    #include <sys/stat.h>
    int  mknod(const  char*  path, mode_t mod,  dev_t dev);
    int  mkfifo(const  char* path,  mode_t  mod);
    注释:这两个函数都能创建一个FIFO文件,该文件是真实存在于文件系统中的。函数 mknod 中参数 path 为创建命名管道的全路径; mod 为创建命名管道的模式,指的是其存取权限; dev为设备值,改值取决于文件创建的种类,它只在创建设备文件是才会用到。 
    返回值:这两个函数都是成功返回 0 ,失败返回 -1
    mknod是比较老的函数,而使用mkfifo函数更加简单和规范,所以建议在可能的情况下,尽量使用mkfifo而不是mknod。
    FIFO文件由mkfifo函数创建,它已经隐含指定了O_CREAT|O_EXCL。也就是说,如果FIFO存在就返回一个EEXIST错误,如果不存在就创建一个新的FIFO。FIFO由open打开而不是mkfifo。因此要打开一个已存在的FIFO或创建一个新的FIFO,应该先调用mkfifo,再检查它是否返回EEXIST错误,若是返回该错误,则改为调用open。
访问命名管道:
    mkfifo函数只是创建一个FIFO文件,要使用命名管道还是将其打开。同打开其他文件一样,FIFO文件也可以使用open调用来打开,但有一点需要注意,就是传递给open调用的是FIFO的路径名,而不是正常的文件。

例子:

fifowrite.c

#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <string.h>
 
int main()
{
    const char *fifo_name = "/tmp/my_fifo";
    int pipe_fd = -1;
    int data_fd = -1;
    int res = 0;
    const int open_mode = O_WRONLY;
    int bytes_sent = 0;
    char buffer[PIPE_BUF + 1];
 
    if (access(fifo_name, F_OK) == -1)
    {
        // 管道文件不存在
        // 创建命名管道
        res = mkfifo(fifo_name, 0777);
        if (res != 0)
        {
            fprintf(stderr, "Could not create fifo %s\n", fifo_name);
            exit(EXIT_FAILURE);
        }
    }
 
    printf("Process %d opening FIFO O_WRONLY\n", getpid());
 
    // 以只写阻塞方式打开FIFO文件,以只读方式打开数据文件
    pipe_fd = open(fifo_name, open_mode);
    data_fd = open("Data.txt", O_RDONLY);
    printf("Process %d result %d\n", getpid(), pipe_fd);
 
    if (pipe_fd != -1)
    {
        int bytes_read = 0;
 
        // 向数据文件读取数据
        bytes_read = read(data_fd, buffer, PIPE_BUF);
        buffer[bytes_read] = '\0';
        while (bytes_read > 0)
        {
            // 向FIFO文件写数据
            res = write(pipe_fd, buffer, bytes_read);
            if (res == -1)
            {
                fprintf(stderr, "Write error on pipe\n");
                exit(EXIT_FAILURE);
            }
 
            // 累加写的字节数,并继续读取数据
            bytes_sent += res;
            bytes_read = read(data_fd, buffer, PIPE_BUF);
            buffer[bytes_read] = '\0';
        }
        close(pipe_fd);
        close(data_fd);
    }
    else
    {
        exit(EXIT_FAILURE);
    }
 
    printf("Process %d finished\n", getpid());
    exit(EXIT_SUCCESS);
}

 

fiforead.c

#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <limits.h>
#include <string.h>
 
int main()
{
    const char *fifo_name = "/tmp/my_fifo";
    int pipe_fd = -1;
    int data_fd = -1;
    int res = 0;
    int open_mode = O_RDONLY;
    char buffer[PIPE_BUF + 1];
    int bytes_read = 0;
    int bytes_write = 0;
    
    // 清空缓冲数组
    memset(buffer, '\0', sizeof(buffer));
 
    printf("Process %d opening FIFO O_RDONLY\n", getpid());
    
    // 以只读阻塞方式打开管道文件,注意与fifowrite.c文件中的FIFO同名
    pipe_fd = open(fifo_name, open_mode);
    
    // 以只写方式创建保存数据的文件
    data_fd = open("DataFormFIFO.txt", O_WRONLY | O_CREAT, 0644);
    printf("Process %d result %d\n", getpid(), pipe_fd);
 
    if (pipe_fd != -1)
    {
        do
        {
            // 读取FIFO中的数据,并把它保存在文件DataFormFIFO.txt文件中
            res = read(pipe_fd, buffer, PIPE_BUF);
            bytes_write = write(data_fd, buffer, res);
            bytes_read += res;
        }
        while (res > 0);
        close(pipe_fd);
        close(data_fd);
    }
    else
    {
        exit(EXIT_FAILURE);
    }
 
    printf("Process %d finished, %d bytes read\n", getpid(), bytes_read);
    exit(EXIT_SUCCESS);
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值