为什么 glibc fcntl 是这样实现的?

why glibc fcntl is implemented as this?

全部;我正在查看 glibc 源代码;我有一个问题是:

int fcntl(int fd, int cmd, ...) {
    va_list ap;
    va_start(ap, cmd);
    void* arg = va_arg(ap, void*);
    va_end(ap);
    return __fcntl64(fd, cmd, arg);
}

这是为什么???!!!

fcntl(fd,cmd); // is this a trouble?
fcntl(fd,cmd,i/*int type*/); // and this?

谢谢大家。

因为这是最便携的方式。系统 ABI could (and sometimes does, e.g. x86-64 Linux ABI) define different calling conventions 用于可变参数和固定元数函数。

可能,较旧的 libc 版本刚刚定义了 int fcntl(int fd, int cmd, void*arg) 并且通常有效(至少如果 arg 未被使用并且在不需要时未被访问),也许在 32 位 x86 上需要 ABI要在堆栈上传递的每个参数。但是在 64 位 x86-64 上,一些参数是通过寄存器传递的(对于可变参数函数,哪些参数以及可能有何不同)。

当然 fcntl(2) and open(2) 可以用两个和三个参数调用。

如果你调用 fcntl(fd, F_SETLK, &mylock) 它应该没问题,但如果你忘记了第三个参数 fcntl(fd,F_SETLK) 它会变成 undefined behavior and you might get some segmentation violation (but probably not). Be very scared 未定义的行为。

您可以使用 gcc -Wall -O -fverbose-asm -S 编译一些示例代码以获取生成的汇编代码(使用寻呼机或编辑器查看发出的 .s 汇编文件)并在阅读您的 ABI 规范后找出答案, 调用是如何完成的。