【发布时间】:2017-05-05 21:42:48
【问题描述】:
我(出于好奇)一直想知道在 x86_64 Linux 上,ioctl 系统调用的用户空间包装器在哪里定义。我的第一个想法是 glibc - 在我的 Fedora 24 盒子上检查已安装版本上的暴露符号后,我可以看到(除非我做错了)libc 将 ioctl 符号暴露为“W”,这意味着它是一个弱符号默认实现。 misc/ioctl.c 的 glibc 源代码树中的默认实现似乎是一个存根,只是将 errno 设置为 ENOSYS 并返回 -1。
无论如何,ioctl 都可以工作(显然,否则我的系统将不会很好用)。我知道它可能是文件中某处的汇编代码,它以某种方式组装和链接,从而覆盖了 glibc 暴露的弱符号。我也知道,应用程序完全有可能直接使用系统调用调用 ioctl,无论是通过 glibc 系统调用包装器还是直接使用程序集。
也就是说,鉴于我碰巧观察到的库源代码 (libdrm) 包含标准 ioctl 头文件 /usr/include/sys/ioctl.h,并且似乎不包含我自己的包装器实现可以看到,我想知道我应该在哪里看。
这是我努力更深入地了解 GNU/Linux 系统的最低级别的一部分。感谢您的任何指点,如果之前有人问过这个问题,我们深表歉意,但如果有的话,我看不到任何答案。
更新:我忽略了上面提到的,但我也检查了内核映射的虚拟 vdso 库 - 我只能在其中找到以下内容:
0000000000000a00 W clock_gettime
0000000000000db0 W getcpu
0000000000000c40 W gettimeofday
0000000000000000 A LINUX_2.6
0000000000000d90 W time
0000000000000a00 T __vdso_clock_gettime
0000000000000db0 T __vdso_getcpu
0000000000000c40 T __vdso_gettimeofday
0000000000000d90 T __vdso_time
更新:我认为 glibc 默认定义是存根是不正确的。正如 cmets 中指出的那样,反汇编表明它正在执行真正的系统调用。我已经发布了一个答案来反映这一点。
【问题讨论】:
-
ldd 和 nm 是我一直在使用的工具。也就是说,我可能没有正确使用 nm - 除了 libc 中的弱符号之外,我在其他任何地方都找不到这个符号。
-
如果您查看 glibc 中的 ioctl 程序集,例如
objdump -D /lib64/libc.so.6,您会发现它确实执行了实际的系统调用 - 它不是来自 misc/ioctl.c 的实现。它的定义很可能是作为 glibc 构建过程的一部分自动生成的,很可能 sysdeps/unix/make-syscalls.sh 是其中的一部分。 -
是的,你是对的——我会回答这个问题,但要提到你的名字。非常感谢您的提示。
标签: c linux system-calls symbols ioctl