本文旨在讨论unix中的系统调用open()
与其阻塞模式,具体为O_NOBLOCK
标记的添加与否对于读FIFO命名管道造成的影响。
1.unix 中的open()
.
open()
定义在头文件<fcntl.h>
中。
open()
的函数原型: int open(const char *path , int aflag , ... /* mode_t mode* */);
亦或是:int openat(int fd, const char *path , int aflag , ... /* mode_t mode* */);
若成功,返回文件描述符fd
, 若失败,返回-1
。
最后一个写作 ...
的参数表明余下的参数的类型和数量可变,它们在创建新文件时发挥作用,也不是本次讨论的重点。
显然, cosnt char* path
是 要开文件的名字(通常是绝对路径)。而aflag
参数则有以下常量通过或运算|
组成。
-
O_RDONlY
只读打开 -
O_WRONlY
只写打开 -
O_RDWR
读写打开 -
O_EXEC
只执行打开 -
O_SEARCH
只搜索(对于目录有此选项)在以上五个常量中必须指定且只能指定一个,而以下常量为可选的。
O_APPEND
每次写入追加到文件末尾。O_CLOEXEC
把FD_CLOEXEC设定为文件描述符。O_CREATE
若文件不存在则创建, 需要指定文件权限位 , 即mode_t 参数。O_DIRECTORY
若path指向的不为目录,则出错。O_EXCL
若同时指定O_CREATE且文件不存在,则出错。可以将测试文件存在和创建文件封装为原子操作。O_NOCTTY
若path引用的是终端设备,则不将该设备分配作为该进程的控制终端。
O_NONBLOCK
若path引用的是一个FIFO,一个块特殊文件或者字符特殊文件,则此选项将本次文件的打开操作和后续的IO操作设置为非阻塞模式。O_SYNC
每次操作需要等待物理IO完成,包括更新文件属性而需要的物理IO。O_TURNC
若文件存且为只写或读写打开,那么将其长度截断为零。O_DSYNC
每次写入需要等待物理IO完成,但是如果不影响读取,则不需要更新文件属性。O_FSYNC
使每一个 以文件描述符为参数的进行的read操作等待,直到所有对文件同一部分的挂起写操作都完成。
2.FIFO的阻塞打开
FIFO是unix 中的命名管道,是unix系统中的IPC技术之一,用于支持进程间通信。FIFO的本质是文件。
创建FIFIO : mkfifo(const char* path , mode_t mode);
\ mkfifo(int fd , char* path , mode_t mode);
该函数原型定义在<sys/stat.h>
中。 若成功将返回0
, 失败将返回-1
。
如果path是绝对路径,则fd参数被忽略。若fd为相对路径,且fd是一个打开目录的有效文件描述符,那么最终路径名和目录有关。
环境: macos 11.2.3
头文件:
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#define PIPE1 "/tmp/pipe1"
例子1 , 阻塞打开FIFO:
int main()
{
//创建管道
mkfifo(PIPE1 , 0777);
//打开管道
int fp1 = open(PIPE1 , O_WRONLY);
printf("%d\n" , fp1);
}
运行程序,发现阻塞在int fp1 = o