深入理解linux内核读书笔记(第十章)

本文详细介绍了系统调用的两种主要方法:int0x80和sysenter,并探讨了它们的执行流程及兼容性问题。此外,还讲解了系统调用参数的传递方式、内核如何验证用户提供的地址的有效性,以及发生页故障的情况。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1. 在执行系统调用时,内核一般返回0表示成功,负数表示失败。用户态的包装函数将内核返回的错误码取负,设置到errno中。

2. 对于没有实现的系统调用,sys_call_table中会存放sys_ni_syscall函数,返回-ENOSYS。

3. 进入系统调用有两种方法:

(1) int 0x80

(2) sysenter

   退出也有两种方式:

        (1) iret

(2) sysexit

4. int 0x80 方式:

         当系统调用结束后,将返回值写入eax所在的内核栈中,之后内核会检查thread_info中的flags,看是否有重新调用等额外的工作要做。最后恢复用户态的寄存器,然后通过

iret返回用户态。

5. sysenter 方式:

       当调用sysenter时,必须填充三个寄存器 (1) SYSENTER_CS_MSR, 内核代码段选择子 (2) SYSENTER_EIP_MSR,内核入口地址 (3)SYSENTER_ESP_MSR, 

       内核栈指针。

6.  内核的堆栈段和数据段是共用的,并且紧挨着内核代码段。 

7. enable_sep_cpu在内核初始化的过程中初始化将__KERNEL_CS写入SYSENTER_CS_MSR寄存器,将sysenter_entry函数的线性地址写入SYSENTER_CS_EIP寄存器,

  将当前cpu TSS的末尾地址写入SYSENTER_CS_ESP中。之后发生系统调用时,切换到内核态后,系统调用处理函数读取esp,然后获取TSS 中esp0的地址,再从esp0中

  读取真正的内核栈地址。

8.为了解决两种调用方式的兼容问题,在内核初始化过程中sysenter_setup函数创建了一个页,叫vsyscall page。里面包含有一个小的ELF共享库。当进程通过execve系统调用 来起动一个elf程序时,vsyscall page中的代码就会动态第链接到进程的地址空间。vsyscall page中的代码会选择最优的方式发起系统调用。

9. vsyscall page 中定义了__kernel_vsyscall和 SYSENTER_RETURN,根据是否支持sysenter来实现该函数。用户态的库发起系统调用时最终会调用__kernel_vsyscall, 退出系统调用时切换回用户态后从SYSENTER_RETURN 开始执行。

10. 系统调用时,参数会先被保存到cpu寄存器中,然后切换到内核态后,从寄存器中复制到内核栈中,供内核的C函数使用。参数不能超过6个,大于6个的话,需要传递栈指针。

11. 在进行参数检查时,内核只需要确定用户传递的地址是否属于用户态的地址范围。更精细的检查会在页故障中进行。

12. 内核通过函数access_ok(verify_area)来检查地址是否合法,该函数内部会检查地址是否越过addr_limit.seg,这个值一般是0xbfffffff。通过get_fs 和set_fs 可以更改这个值。

13. 发生页故障的三种情况:

(1)内核去访问一个属于该进程的页,但是该页面不存在或者是只读,内核必须分配一个新页。

        (2)内核去访问一个属于该进程的页,但是该页对应的页表不存在,内核必须建立页表。

        (3)内核bug或者是硬件的错误,内核会oops。

        (4)内核在处理系统调用过程中,去读去用户穿过来的地址,但是该地址并不在进程的地址空间内。

14. 由于内核访问用户空间的函数比小少,因此可以将这些函数的指令地址记录在一个异常表中,当发生页故障时,只要检查出错的指令是否在异常表中,就可以确定是否是由于系统调用参数异常导致。

15. exception_table_entry结构中包含一个指令的地址和fixup代码的地址。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值