【问题标题】:why glibc fcntl is implemented as this?为什么 glibc fcntl 是这样实现的?
【发布时间】:2015-12-27 12:39:43
【问题描述】:

全部;我现在正在查看 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?

谢谢大家。

【问题讨论】:

    标签: glibc fcntl variadic-functions


    【解决方案1】:

    因为它是最便携的方式。系统ABI 可以(有时确实,例如x86-64 Linux ABI)为可变参数和固定参数函数定义不同的calling conventions

    可能,较旧的 libc 版本刚刚定义了 int fcntl(int fd, int cmd, void*arg) 并且通常可以正常工作(至少在不使用 arg 并且在不需要时不访问的情况下),可能在 32 位 x86 上,ABI 需要传递每个参数堆栈。但是在 64 位 x86-64 上,一些参数由寄存器传递(哪些参数以及可变参数函数可能不同)。

    当然,fcntl(2)open(2) 可以同时使用两个和三个参数来调用。

    如果你调用 fcntl(fd, F_SETLK, &mylock) 应该没问题,但如果你忘记了 fcntl(fd,F_SETLK) 的第三个参数,它会变成 undefined behavior 并且你可能会遇到一些分段违规(但可能不会)。成为未定义行为的very scared

    您可以使用gcc -Wall -O -fverbose-asm -S 编译一些示例代码以获取生成的汇编程序代码(使用分页器或编辑器查看发出的.s 汇编程序文件)并在阅读您的ABI 规范后弄清楚调用是如何真正完成的.

    【讨论】:

    • 当用fcntl(fd,cmd); 调用时;会va_arg(ap,void*) SIGSEGV 还是其他错误?谢谢!
    • @qwertimg 显然,在运行 glibc 并支持 fcntl 的平台上,以及用于编译 glibc 的编译器版本和选项,它不会。您仍然不应该在代码中这样做,因为您可能不在其中一个平台上,或者您可能正在使用不同的编译器。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-10-31
    • 2011-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多