详解:命名管道的打开规则

前言

        在前面的文章中我们已经对命名管道进行了简单介绍,我们知道命名管道的本质就是文件系统中的一个特殊设备文件,即管道文件(FIFO)。虽然它和其他普通文件的用途不同,但它的打开方式却和普通文件相同,都是通过调用open函数来打开。通常而言,打开管道文件的方式有以下几种:

(1)只读且阻塞方式
        open(const char *pathname, O_RDONLY);
(2)只读且非阻塞方式
        open(const char *pathname, O_RDONLY | O_NONBLOCK);
(3)只写且阻塞方式
        open(const char *pathname, O_WRONLY);
(4)只写且非阻塞方式
        open(const char *pathname, O_WRONLY | O_NONBLOCK);
注:
        在这里我们需要注意一点,就是不能以 O_RDWR 方式打开管道文件,这种行为是未定义的。倘若有一个进程以读写方式打开了某个管道,那么该进程写入的数据又会被该进程本身读取,而管道一般只用于进程间的单向数据通信。

        对于上述的4种打开方式,我们将在接下来的部分进行详细介绍,并分析每一种方式所产生的的结果。

一、只读方式

1. 阻塞模式(默认)

【示例】
        在命令行模式下使用 mkfifo fifo 创建一个命名管道fifo,验证以只读且阻塞方式打开该命名管道情况下的结果。
【代码】

#include <stdio.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
         
int main() {    
    int fd = open("fifo", O_RDONLY); //以只读且阻塞方式打开命名管道    
    if(fd == -1) {    
        printf("Failed to open pipeline.\n");    
        return -1;    
    }    
    else {    
        printf("Successfully opened the pipeline.\n");    
    }    
         
    char buf[20] = {0};    
    read(fd, buf, 20);    
    printf("read buf: %s\n", buf);                                                                                                                    
         
    close(fd);    
         
    return 0;    
}

【执行结果】
在这里插入图片描述
【分析】
        从执行结果来看,在只读且阻塞方式下打开命名管道,open 函数会进入阻塞等待状态,直到有相关进程为写而打开该管道。(另一进程代码可参考下面只写且阻塞方式情况下的示例)

2. 非阻塞模式

【示例】
        在命令行模式下使用 mkfifo fifo 创建一个命名管道fifo,验证以只读且非阻塞方式打开该命名管道情况下的结果。
【代码】

#include <stdio.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
         
int main() {    
    int fd = open("fifo", O_RDONLY | O_NONBLOCK); //以只读且非阻塞方式打开命名管道    
    if(fd == -1) {                                                                                                                                    
        printf("Failed to open pipeline.\n");    
        return -1;    
    }    
    else {    
        printf("Successfully opened the pipeline.\n");    
        perror("result");    
    }    
         
    char buf[20] = {0};    
    read(fd, buf, 20);    
         
    close(fd);    
         
    return 0;    
}

【执行结果】
在这里插入图片描述
【分析】
        从执行结果来看,在只读且非阻塞方式下打开命名管道,open 函数会立即成功返回,即管道成功打开。

3. 总结

模式结果
阻塞模式(O_NONBLOCK disable)open 阻塞直到有相关进程为写而打开该管道
非阻塞模式(O_NONBLOCK enable)open 成功返回

二、只写方式

1. 阻塞模式(默认)

【示例】
        在命令行模式下使用 mkfifo fifo 创建一个命名管道fifo,验证以只写且阻塞方式打开该命名管道情况下的结果。
【代码】

#include <stdio.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
#include <string.h>    
         
int main() {    
    int fd = open("fifo", O_WRONLY); //以只写且阻塞方式打开命名管道    
    if(fd == -1) {    
        printf("Failed to open pipeline.\n");    
        return -1;    
    }    
    else {    
        printf("Successfully opened the pipeline.\n");    
    }    
         
    char buf[] = "Hello FIFO";    
    write(fd, buf, strlen(buf));    
    printf("write buf: %s\n", buf);                                                                                                                   
         
    close(fd);    
         
    return 0;    
}

【执行结果】
在这里插入图片描述

【分析】
        从执行结果来看,在只写且阻塞方式下打开命名管道,open 函数会进入阻塞等待状态,直到有相关进程为读而打开该管道。(另一进程代码可参考上面只读且阻塞方式情况下的示例)

2. 非阻塞模式

【示例】
        在命令行模式下使用 mkfifo fifo 创建一个命名管道fifo,验证以只写且非阻塞方式打开该命名管道情况下的结果。
【代码】

#include <stdio.h>    
#include <unistd.h>    
#include <sys/types.h>    
#include <sys/stat.h>    
#include <fcntl.h>    
#include <errno.h>    
#include <string.h>    
         
int main() {    
    extern int errno;    
         
    int fd = open("fifo", O_WRONLY | O_NONBLOCK); //以只写且非阻塞方式打开命名管道                                                                    
    if(fd == -1) {    
        printf("Failed to open pipeline.\n");    
        printf("errno: %d\n", errno);    
        perror("result");    
        return -1;    
    }    
    else {    
        printf("Successfully opened the pipeline.\n");    
    }    
         
    char buf[] = "Hello FIFO";    
    write(fd, buf, strlen(buf));    
         
    close(fd);    
         
    return 0;    
}

【执行结果】
在这里插入图片描述
【分析】
        从执行结果来看,在只写且非阻塞方式下打开命名管道,open 函数会立即出错返回,即管道打开失败,并且 errno 被置为 ENXIO,错误信息为 No such device or address

3. 总结

模式结果
阻塞模式(O_NONBLOCK disable)open 阻塞直到有相关进程为读而打开该管道
非阻塞模式(O_NONBLOCK enable)open 失败返回,并置 errno 为 ENXIO
  • 6
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值