操作系统原理(4)

系统调用:
1.glibc 对系统调用的封装
    在 glibc 的源代码中,有个文件 syscalls.list,里面列着所有 glibc 的函数对应的系统调用。glibc 还有一个脚本 make-syscall.sh,可以根据上面的配置文件,对于每一个封装好的系统调用,生成一个文件,这个文件里面定义了一些宏。glibc 还有一个文件 syscall-template.S,使用上面这个宏,定义了这个系统调用的调用方式。对于任何一个系统调用,会调用 DO_CALL(一个宏)。
2.32 位系统调用过程
    将请求参数放在寄存器里面,根据系统调用的名称,得到系统调用号,放在寄存器 eax 里面,然后执行 ENTER_KERNEL。
    ENTER_KERNEL 是什么呢?
#define ENTER_KERNEL int $0x80
int $0x80 就是触发一个软中断,通过它就可以陷入(trap)内核。
    trap_init()中有 set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32) 这个函数,当接收到一个系统调用的时候,entry_INT80_32 就被调用。通过 push 和 SAVE_ALL 将当前用户态的寄存器,保存在 pt_regs 结构里面,然后调用do_syscall_32_irqs_on。在 do_syscall_32_irqs_on 中将系统调用号从 eax 里面取出来,然后根据系统调用号,在系统调用表中找到相应的函数进行调用,并将寄存器中保存的参数取出来,作为函数参数。
    当系统调用结束之后,在 entry_INT80_32 之后,紧接着调用的是 INTERRUPT_RETURN(#define INTERRUPT_RETURN iret)返回用户态。
3.64 位系统调用过程
    将系统调用名称转换为系统调用号,放到寄存器 rax,用 syscall 指令实现调用。
trap_init()调用 cpu_init->syscall_init,里面有这样的代码:
wrmsrl(MSR_LSTAR, (unsigned long)entry_SYSCALL_64);
    当 syscall 指令调用的时候,会从MSR_LSTAR这个寄存器里面拿出函数地址来调用,也就是调用 entry_SYSCALL_64。在entry_SYSCALL_64中先保存了很多寄存器到 pt_regs 结构里面,然后调用do_syscall_64。在 do_syscall_64 里面,从 rax 里面拿出系统调用号,然后根据系统调用号,在系统调用表 sys_call_table 中找到相应的函数进行调用,并将寄存器中保存的参数取出来,作为函数参数。
    64 位的系统调用返回的时候,执行的是 USERGS_SYSRET64,
        #define USERGS_SYSRET64
        swapgs;
         sysretq;
返回用户态的指令为 sysretq。
4.系统调用表(sys_call_table)
  32 位的系统调用表定义在 arch/x86/entry/syscalls/syscall_32.tbl 文件里。
  64 位的系统调用定义在 arch/x86/entry/syscalls/syscall_64.tbl 里。
  系统调用在内核中的实现函数要有一个声明。声明在 include/linux/syscalls.h 文件。
实现这个系统调用,一般在一个.c 文件里面。
  在编译的过程中根据 syscall_32.tbl 和 syscall_64.tbl 生成自己的 unistd_32.h 和 unistd_64.h。unistd_32.h 和 unistd_64.h 是对应的系统调用号和系统调用实现函数之间的对应关系。
  在文件 arch/x86/entry/syscall_xx.c,定义了这样一个表,里面 include 了这个头文件,从而所有的 sys_ 系统调用都在这个表里面了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值