您的位置:首页 > 运维架构 > Linux

linux vdso与vsyscall相关内容总结

2016-06-12 23:20 531 查看
在上一篇blog里,简单分析了64位linux下系统调用的执行过程,其中还剩下两点内容:vdso与vsyscall。vdso的全称是虚拟动态共享库(virtual dynamic shared library),而vsyscall的全称是虚拟系统调用(virtual system call)。关于 vdso与vsyscall的介绍,请见以下这篇blog,内容上这篇blog分析的非常好,并且是以x86-64位的linux最为实例进行讲解,但这个系列blog是直接从源码出发,我现在分析内核或glibc的思路是从现象出发,层层深入,所以在思路上有些冲突。

https://0xax.gitbooks.io/linux-insides/content/SysCall/syscall-3.html

 在推荐另一篇blog:http://www.lenky.info/archives/2013/02/2199

同样是对64位linux的系统调用机制进行研究,但其中的某些实验我没有能够复现。

好,言归正传。

先来看vdso与vsyscall的出现原因:由于进行系统调用时,操作系统要由用户态切换到内核态,而这一操作是非常浪费时间的操作,无论采用早期的int 0x80/iret中断,还是sysenter/sysexit指令,再到syscall/sysexit指令。另一方面,某些系统调用并不会向内核提交参数,而仅仅只是从内核里请求读取某个数据,例如gettimeofday(),内核在处理这部分系统调用时可以把系统当前时间写在一个固定的位置,而应用程序直接从该位置简单读取即可,无需发起系统调用。内核与用户态程序之间进行数据交互的方法就是mmap。但由于vsyscall采用固定地址映射的方式,所以存在一定的安全隐患,这一方式便被vdso所改进,vdso的随机映射在一定程度上缓解了安全威胁。虽然有了vdso,但从历史兼容性上来讲,vsyscall不能就此完全抛弃,否则将导致一些陈旧的(特别是静态连接的)应用程序无法执行,因此现在在我的3.19内核上,将同时看到vdso和vsyscal。

举个简单的例子:

cat /proc/self/maps
00400000-0040c000 r-xp 00000000 08:08 2883607 /bin/cat
0060b000-0060c000 r--p 0000b000 08:08 2883607 /bin/cat
0060c000-0060d000 rw-p 0000c000 08:08 2883607 /bin/cat
01778000-01799000 rw-p 00000000 00:00 0 [heap]
7eff551eb000-7eff558cd000 r--p 00000000 08:08 401027 /usr/lib/locale/locale-archive
7eff558cd000-7eff55a8d000 r-xp 00000000 08:08 3412306 /lib/x86_64-linux-gnu/libc-2.21.so
7eff55a8d000-7eff55c8d000 ---p 001c0000 08:08 3412306 /lib/x86_64-linux-gnu/libc-2.21.so
7eff55c8d000-7eff55c91000 r--p 001c0000 08:08 3412306 /lib/x86_64-linux-gnu/libc-2.21.so
7eff55c91000-7eff55c93000 rw-p 001c4000 08:08 3412306 /lib/x86_64-linux-gnu/libc-2.21.so
7eff55c93000-7eff55c97000 rw-p 00000000 00:00 0
7eff55c97000-7eff55cbb000 r-xp 00000000 08:08 3412278 /lib/x86_64-linux-gnu/ld-2.21.so
7eff55e78000-7eff55e9d000 rw-p 00000000 00:00 0
7eff55eb8000-7eff55eba000 rw-p 00000000 00:00 0
7eff55eba000-7eff55ebb000 r--p 00023000 08:08 3412278 /lib/x86_64-linux-gnu/ld-2.21.so
7eff55ebb000-7eff55ebc000 rw-p 00024000 08:08 3412278 /lib/x86_64-linux-gnu/ld-2.21.so
7eff55ebc000-7eff55ebd000 rw-p 00000000 00:00 0
7ffc08293000-7ffc082b4000 rw-p 00000000 00:00 0 [stack]
7ffc082e4000-7ffc082e6000 r--p 00000000 00:00 0 [vvar]
7ffc082e6000-7ffc082e8000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]此处可以清晰的看到在进程空间里同时存在vdso与vsyscall,我曾试着将这两个文件转储出来,不过还没有成功。
所以我也就没有办法从现象出发对源码进行分析。

此处还要提一个函数名为__kernel_vsyscall,名字和vsyscall很像,不过正好相反,这个函数是与vdso相关的函数。根据《深入理解linux内核》,__kernel_vsyscall是为兼容int 0x80与sysenter两种系统调用触发方式,而存在的函数。但在x64上不再需要__kernel_vsyscall,因为它只有一种调用方式,即syscall指令。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息