zoukankan      html  css  js  c++  java
  • linux 系统调用VDSO

    以软中断或指令方式执行的系统调用,需要切换到内核空间,无论采用早期的int 0x80/iret中断,还是sysenter/sysexit指令,再到syscall/sysexit指令,是一个比较慢的操作。例如像gettimeofday()这种,若每次为了从内核读取时间值而都切换上下文的话,成本就太高了,这些系统调用并不会向内核提交参数,而仅仅只是从内核里请求读取某个数据,,内核在处理这部分系统调用时可以把系统当前时间写在一个固定的位置,而应用程序直接从该位置简单读取即可,无需发起系统调用。。所以Linux推出了一些措施,来帮助这些系统调用执行更快,那就是vsyscall和vdso。在64位系统上执行cat /proc/self/maps可以看到:

    vsyscall

    首先谈vsyscall,这是内核最先引入的机制。内核直接把类似gettimeofday()这种功能简单的函数的二进制实现,直接映射到任务的用户空间中,这样任务就可以在用户空间把这些系统调用当成普通函数来用,这样效率就大大提升。

    但vsyscall有一些致命的问题,一是vsyscall的用户空间映射所在的地址是固定不变的,容易被别有用心的人利用;二是vsyscall能支持的系统调用数有限,不利于扩展。所以,渐渐地一些替代方案就产生了。

    vdso

    vdso是vsyscall的主要替代方案,全称是Virtual Dynamic Shared Object. 这是一个虚拟动态链接库,内核把那些系统调用放到这里面,然后用户程序在启动的时候通过动态链接操作,把这个vdso链到自己的内存空间中来。动态链接保证了vdso每次所在的地址都不一样,所以不太容易被利用,而且可以支持数量较多的系统调用。

    Glibc封装

    Glibc为系统调用提供了封装,保证使用的是当前机器上能够支持的最快的调用。我们所要做的只是直接调用Glibc的接口函数而已,如gettimeofday。但是Linux也提供了syscall()来让你直接通过中断的方式进行系统调用 

    此处还要提一个函数名为__kernel_vsyscall,名字和vsyscall很像,不过正好相反,这个函数是与vdso相关的函数。根据《深入理解linux内核》,__kernel_vsyscall是为兼容int 0x80与sysenter两种系统调用触发方式,而存在的函数。但在x64上不再需要__kernel_vsyscall,因为它只有一种调用方式,即syscall指令。

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

            vdso=           [X86,SH]
                            On X86_32, this is an alias for vdso32=.  Otherwise:
    
                            vdso=1: enable VDSO (the default)
                            vdso=0: disable VDSO mapping
    
            vdso32=         [X86] Control the 32-bit vDSO
                            vdso32=1: enable 32-bit VDSO
                            vdso32=0 or vdso32=2: disable 32-bit VDSO
    
                            See the help text for CONFIG_COMPAT_VDSO for more
                            details.  If CONFIG_COMPAT_VDSO is set, the default is
                            vdso32=0; otherwise, the default is vdso32=1.
    
                            For compatibility with older kernels, vdso32=2 is an
                            alias for vdso32=0.
    
                            Try vdso32=0 if you encounter an error that says:
                            dl_main: Assertion `(void *) ph->p_vaddr == _rtld_local._dl_sysinfo_dso' failed!
  • 相关阅读:
    iOS- 移动端Socket UDP协议广播机制的实现
    iOS- 三步快速集成社交化分享工具ShareSDK
    iOS- iOS 7 的后台多任务 (Multitasking) 对比之前的异同、具体机制、变化
    iOS- Exception异常处理
    17. Subsets【medium】
    zookeeper程序员指南
    error while loading shared libraries错误解决
    82. Single Number【easy】
    53. Reverse Words in a String【easy】
    查看linux内核和版本信息
  • 原文地址:https://www.cnblogs.com/dream397/p/14250752.html
Copyright © 2011-2022 走看看