Linux下的VDSO
VDSO(Virtual Dynamically-linked Shared Object)是个很有意思的东西, 它将内核态的调用映射到用户态的地址空间中, 使得调用开销更小, 路径更好.
开销更小比较容易理解, 那么路径更好指的是什么呢? 拿x86下的系统调用举例, 传统的int 0x80有点慢, Intel和AMD分别实现了sysenter, sysexit和syscall, sysret, 即所谓的快速系统调用指令, 使用它们更快, 但是也带来了兼容性的问题. 于是Linux实现了vsyscall, 程序统一调用vsyscall, 具体的选择由内核来决定. 而vsyscall的实现就在VDSO中.
Linux(kernel 2.6 or upper)环境下执行ldd /bin/sh, 会发现有个名字叫linux-vdso.so.1(老点的版本是linux-gate.so.1)的动态文件, 而系统中却找不到它, 它就是VDSO. 例如:
$ ldd /bin/sh
linux-vdso.so.1 => (0x00007fff2f9ff000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f28d5b36000)
/lib64/ld-linux-x86-64.so.2 (0x00007f28d5eca000)
linux-gate.so.1的地址是0xffffe000. 较新的内核提供了进程随机地址化功能, linux-vdso.so.1的地址每次cat /proc/self/maps都会变化, 想把它从/proc/self/mem中dd出来反汇编玩儿的同学请先:
echo "0" > /proc/sys/kernel/randomize_va_space
不光是快速系统调用, glibc现在也提供了VDSO的支持, open(), read(), write(), gettimeofday()都可以直接用VDSO中的实现, 使得这些调用更快, glibc更兼容, 内核新特性在不影响glibc的情况下也可以更快的部署. 实在是Nice!
ref:
1, http://lwn.net/Articles/18414/
2, http://www.ibm.com/developerworks/cn/linux/kernel/l-k26ncpu/index.html