当设置 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(在“应失败”或“可能失败”部分)适合指示此问题,即使您 可以检测到它。
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 typemode_t
modified as follows: ...
它没有指定当您省略该参数时会发生什么,因此建议您确保它存在(在客户端)。最可能的情况是它将使用是参数所在的位置(无论是在寄存器还是内存中,取决于调用约定),并且这是正确值的可能性很小。
Linux 文档在这个问题上有这样的说法(我的重点):
The
mode
argument must be supplied ifO_CREAT
orO_TMPFILE
is specified inflags
; if it is not supplied, some arbitrary bytes from the stack will be applied as the file mode.
现在,当然,这不是标准文档,其中术语“必须”是您执行此操作的明确要求(否则所有关于效果的赌注都没有),但您可能应该 以这种方式阅读。因此,再一次,你应该确保你提供它。
所以我会说你的处理方式如下:
- 如果在 client/caller 一侧,请确保提供模式。其他任何事情都违反了合同。
- 在 server/callee 方面,假设呼叫者已经提供了它,因为如果他们没有提供,他们就会破坏合同。 POSIX 中似乎没有合适的错误 return(在“应失败”或“可能失败”部分)适合指示此问题,即使您 可以检测到它。