vdso 是 virtual dynamic shared object 的缩写,表示一段内存映射,它包含的是一个ELF共享目标文件.so,为了用户态对频繁使用的系统调用进行的优化,即把系统调用改成用户态的函数调用,提升系统调用速度。
vdsomunge 源代码位于 kernel/arch/arm/vdso/vdsomunge.c,编译内核的时候会将它编译成一个可执行的ELF文件,程序先对 e_type、e_ident、e_machine、e_flags系列ELF文件标志位进行了检测与相应的错误处理,然后再使用mmap进行内存映射。
ldd /bin/ps
linux-vdso.so.1 (0x00007ffdaaf1e000)
libprocps.so.8 => /lib/x86_64-linux-gnu/libprocps.so.8 (0x00007f09f1c4f000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f09f1c49000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f09f1a57000)
libsystemd.so.0 => /lib/x86_64-linux-gnu/libsystemd.so.0 (0x00007f09f19a8000)
/lib64/ld-linux-x86-64.so.2 (0x00007f09f1cd9000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007f09f199e000)
liblzma.so.5 => /lib/x86_64-linux-gnu/liblzma.so.5 (0x00007f09f1975000)
liblz4.so.1 => /usr/lib/x86_64-linux-gnu/liblz4.so.1 (0x00007f09f1952000)
libgcrypt.so.20 => /usr/lib/x86_64-linux-gnu/libgcrypt.so.20 (0x00007f09f1834000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f09f1811000)
libgpg-error.so.0 => /lib/x86_64-linux-gnu/libgpg-error.so.0 (0x00007f09f17ee000)
ldd /bin/ls
linux-vdso.so.1 (0x00007ffcb99c9000)
libselinux.so.1 => /lib/x86_64-linux-gnu/libselinux.so.1 (0x00007f78bbf8f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f78bbd9d000)
libpcre2-8.so.0 => /usr/lib/x86_64-linux-gnu/libpcre2-8.so.0 (0x00007f78bbd0c000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f78bbd06000)
/lib64/ld-linux-x86-64.so.2 (0x00007f78bbffd000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f78bbce3000)
每个使用了动态库的程序都使用了 linux-vdso.so 库,其它的库都有路径,唯独vsdo库是个地址,其映射的基地址每次都是不同的,以解决固定映射地址的安全问题。
通过 proc 文件查看系统中进程的 vsdo 内存映射
cat /proc/1/maps
.......
7ffd221d8000-7ffd221f9000 rw-p 00000000 00:00 0 [stack]
7ffd221fc000-7ffd221ff000 r--p 00000000 00:00 0 [vvar]
7ffd221ff000-7ffd22200000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]
通过 dd 把 vsdo 内存映射里的数据拷出来查看,是几个快速系统调用的函数实现:
dd if=/proc/1/mem of=/home/share/work/ac/vdso.so skip=140725175971840 ibs=1 count=8192
objdump -T /home/share/work/ac/vdso.so
/home/share/work/ac/vdso.so: file format elf64-x86-64
DYNAMIC SYMBOL TABLE:
0000000000000840 w DF .text 00000000000001e0 LINUX_2.6 clock_gettime
0000000000000680 g DF .text 00000000000001a7 LINUX_2.6 __vdso_gettimeofday
0000000000000a20 w DF .text 0000000000000005 LINUX_2.6 clock_getres
0000000000000a20 g DF .text 0000000000000005 LINUX_2.6 __vdso_clock_getres
0000000000000680 w DF .text 00000000000001a7 LINUX_2.6 gettimeofday
0000000000000830 g DF .text 0000000000000010 LINUX_2.6 __vdso_time
0000000000000830 w DF .text 0000000000000010 LINUX_2.6 time
0000000000000840 g DF .text 00000000000001e0 LINUX_2.6 __vdso_clock_gettime
0000000000000000 g DO *ABS* 0000000000000000 LINUX_2.6 LINUX_2.6
0000000000000a30 g DF .text 0000000000000025 LINUX_2.6 __vdso_getcpu
0000000000000a30 w DF .text 0000000000000025 LINUX_2.6 getcpu
备注 : 140725175971840 为 0x7ffd221ff000 的十进制数。