linux 系统调用 open() 位掩码

linux syscall open() bitmask

我想知道 Linux 系统调用 int open(const char *pathname, int flags) 中有以下代码行的目的是什么:

if (flags & ~(O_RDONLY | O_WRONLY | O_CREAT | O_RDWR | O_TRUNC | O_APPEND))
{
  return -1;
}

此行检查您的文件是否只有这些属性可用:
O_RDONLY : 只读文件
O_WRONLY : 只写文件
O_CREAT : 如果文件不存在则创建文件
O_RDWR : 读写文件
O_TRUNC : 如果文件已经存在并且是一个普通文件并且访问 模式允许写入(即 O_RDWR 或 O_WRONLY)它将是 截断为长度 0。
O_APPEND : 文件以附加模式打开

在不知道 O_RDONLYO_WRONLYO_RDWR 的实际值的情况下,实际上不可能确定该代码的实际作用。

密码

if (flags & ~(O_RDONLY | O_WRONLY | O_CREAT | O_RDWR | O_TRUNC | O_APPEND))
{
  return -1;
}

是不可移植的,严格来说,在可以访问和控制标志的实际值的实际系统实现之外是无效的。 Per POSIX,标志 O_RDONLYO_WRONLYO_RDWRNOT 位标志:

Values for oflag are constructed by a bitwise-inclusive OR of flags from the following list, defined in . Applications shall specify exactly one of the first five values (file access modes) below in the value of oflag:

O_EXEC Open for execute only (non-directory files). The result is unspecified if this flag is applied to a directory.

O_RDONLY Open for reading only.

O_RDWR Open for reading and writing. The result is undefined if this flag is applied to a FIFO.

O_SEARCH Open directory for search only. The result is unspecified if this flag is applied to a non-directory file.

O_WRONLY Open for writing only.

由于这些标志不是基于位的,而是基于实际值的,因此在不知道它们在所用系统上的实际值的情况下,无法通过按位运算检测到它们的存在或不存在。

此代码使用了多个标志,违反了 POSIX 规范:

O_RDONLY | O_WRONLY | O_CREAT | O_RDWR | O_TRUNC | O_APPEND

理论上它可以产生一个无意义的位值,不能用于对任何东西进行有效的按位比较。

RATIONALE section of the open() POSIX documentation 甚至解决了 open() 标志的非基于位标志的性质:

基本原理

In historical implementations the value of O_RDONLY is zero. Because of that, it is not possible to detect the presence of O_RDONLY and another option. Future implementations should encode O_RDONLY and O_WRONLY as bit flags so that:

O_RDONLY | O_WRONLY == O_RDWR

只有当 O_RDONLYO_WRONLYO_RDWR 不是基于位的标志时,该评论才有意义。