当设置 O_CREAT 位但只为 open() 提供两个参数时会发生什么?

What happens when setting the O_CREAT bit but only providing two parameters for open()?

,我问的是为 OS161 实现 sys_open 系统调用的任务,它将由 open 函数调用。

open函数的定义如下:

int open(const char *filename, int flags, ...);

手册页如下所示:

剧情简介

#include <unistd.h>
#include <fcntl.h>

int
open(const char *filename, int flags);
int
open(const char *filename, int flags, mode_t mode);

由于它是一个可变参数函数,它可以接受与传递的参数一样多的参数,但只定义了具有 2 个或 3 个参数的情况。

我的问题是如何确定传递给open的参数个数,是2个还是3个。如果O_CREAT位设置在flags中的答案方式,然后提供 mode

但我在 OS 中看到一些代码如下所示:

fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC);

在这种情况下,mode 的值将是 a2 寄存器中的任何值,而不是有效值。

1 - 在这种情况下会发生什么,在这种情况下我应该怎么做?参数是如何传递的?它是否在 a2 寄存器中传递了一个零(不太可能发生)?或者它只是留下寄存器中的任何值?无论如何,我如何确定最后一个参数是否有效?

我曾经让 sys_open 函数接收 3 个参数,如果设置了 O_CREAT 位,则只使用最后一个 (mode)。但是现在由于可以在设置位且没有第三个参数的情况下调用该函数,我仍然可以使用 mode 的值,即使它无效。

2 - 处理参数的逻辑应该是什么?

syscall的发出方式在上述问题中有详细说明。

POSIX 文档简单地指出:

mode shall be set to the value of the argument following the oflag argument taken as type mode_t modified as follows: ...

它没有指定当您省略该参数时会发生什么,因此建议您确保它存在(在客户端)。最可能的情况是它将使用参数所在的位置(无论是在寄存器还是内存中,取决于调用约定),并且这是正确值的可能性很小。


Linux 文档在这个问题上有这样的说法(我的重点):

The mode argument must be supplied if O_CREAT or O_TMPFILE is specified in flags; if it is not supplied, some arbitrary bytes from the stack will be applied as the file mode.

现在,当然,这不是标准文档,其中术语“必须”是您执行此操作的明确要求(否则所有关于效果的赌注都没有),但您可能应该 以这种方式阅读。因此,再一次,你应该确保你提供它。

所以我会说你的处理方式如下:

  • 如果在 client/caller 一侧,请确保提供模式。其他任何事情都违反了合同。
  • 在 server/callee 方面,假设呼叫者已经提供了它,因为如果他们没有提供,他们就会破坏合同。 POSIX 中似乎没有合适的错误 return(在“应失败”或“可能失败”部分)适合指示此问题,即使您 可以检测到它。