【问题标题】:Having trouble finding the method __kernel_vsyscall within the Linux kernel在 Linux 内核中找不到方法 __kernel_vsyscall
【发布时间】:2012-10-16 00:14:12
【问题描述】:

我正在寻找用于进行系统调用的 linux 内核中的 __kernel_vsyscall 方法。我想观察它的代码以了解更多关于它的信息,但我的 grep 搜索似乎无法找出它,而且我在互联网上找不到它的位置。谁能指出我的确切位置?它可以被操纵吗?

感谢您的帮助!

【问题讨论】:

    标签: linux linux-kernel kernel


    【解决方案1】:

    假设您的当前目录位于 linux 内核源代码的头部,这里是定义 __kernel_vsyscall 符号的文件的位置。 (下图只针对x86,很多其他硬件架构中还不存在)。

    ./arch/x86/vdso/vdso32/syscall.S:
    __kernel_vsyscall:
    
    ./arch/x86/vdso/vdso32/sysenter.S:
    __kernel_vsyscall:
    
    ./arch/x86/vdso/vdso32/int80.S:
    __kernel_vsyscall:
    

    如您所见,它本质上是在三个文件中声明和实现的:int80.S、sysenter.S 和 syscall.S。

    采用 syscall.S:

    __kernel_vsyscall:
    .LSTART_vsyscall:
            push    %ebp
    .Lpush_ebp:
            movl    %ecx, %ebp
            syscall
            movl    $__USER32_DS, %ecx
            movl    %ecx, %ss
            movl    %ebp, %ecx
            popl    %ebp
    

    如果您阅读上述文件和“arch/x86/vdso/vdso32/sigreturn.S”的组合,则上面的“syscall”实际上解析为“int 0x80”。

    而对于sysenter.S,它使用intel汇编指令“sysenter”来实现系统调用转换。

    对于 int80.S,它使用“int 0x80”进行系统调用转换。

    如果你问系统调用实现的方法是什么,请查看 arch/x86/vdso/vdso32-setup.c:

    int __init sysenter_setup(void)
    {
            void *syscall_page = (void *)get_zeroed_page(GFP_ATOMIC);
            const void *vsyscall;
            size_t vsyscall_len;
    
            vdso32_pages[0] = virt_to_page(syscall_page);
    
    #ifdef CONFIG_X86_32
            gate_vma_init();
    #endif
    
            if (vdso32_syscall()) {
                    vsyscall = &vdso32_syscall_start;
                    vsyscall_len = &vdso32_syscall_end - &vdso32_syscall_start;
            } else if (vdso32_sysenter()){
                    vsyscall = &vdso32_sysenter_start;
                    vsyscall_len = &vdso32_sysenter_end - &vdso32_sysenter_start;
            } else {
                    vsyscall = &vdso32_int80_start;
                    vsyscall_len = &vdso32_int80_end - &vdso32_int80_start;
            }
    
            memcpy(syscall_page, vsyscall, vsyscall_len);
            relocate_vdso(syscall_page);
    
            return 0;
    }
    

    如您所见,现代操作系统更喜欢 sysenter 方法,因为它比 int80 方法快。 (象征性地,“vds32_syscall_start”将回退到 int80)。

    【讨论】:

      【解决方案2】:

      有趣的是,在您的互联网搜索中,您没想到会搜索 stackoverflow.com:What is __kernel_vsyscall?

      要回答您更具体的问题,符号本身似乎是在(对于 x86)arch/x86/vdso 中定义的。它在汇编中,而不是 C 中。

      【讨论】:

        猜你喜欢
        • 2017-04-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多