系统调用

系统调用是CPU主动地、同步地进入系统空间的手段。

中断有可能发生在CPU已经运行在系统空间的时候,而系统调用却只发生于用户空间。CPU在穿过陷阱门进入系统内核时并不自动关中断,所以系统调用的过程是可中断的。

Linux内核在系统调用时是通过寄存器而不是通过堆栈传递参数的。

发生系统调用,首先检验当前的准入等级与CPU当前的运行等级。然后通过函数指针找到system_call()。

system_call():首先是将寄存器%eax的内容压入堆栈,系统堆栈中这个位置在代码中称为orgi_ax,用于存放系统调用号。系统调用中可以用寄存器来进行传递独立参数。独立参数不能超过5个,且与压入的次序有关。

宏调用GET_CURRENT(%ebx)使寄存器%ebx指向当前进程的task_struct结构。然后检验寄存器%eax中的系统调用号是否超出了范围。在task_struct数据结构中有个成分flags,其中有个标志位叫PT_TRACESYS。一个进程可以通过系统调用ptrace(),将一个子进程的PT_TRACESYS标志位设成1,从而跟踪该子程序的系统调用。

系统调用时,当这个操作的源在用户空间,而目标在系统空间时,要通过一个宏操作copy_from_user( )来完成复制。

对于bad_area,当异常发生于当CPU运行在系统空间的时候,虽然访问失败的目标地址在空户空间中,但CPU的“执行地址”却是在系统空间中。如果内核能够在一个“异常表”中找到发生异常的指令所在的地址,并得到相应的“修复”地址fixup,就将CPU在异常返回后将要重新执行的地址替换成这个“修复”地址。

copy_from_user() 》 _ _copy_user_zeroing( )

在执行的过程中,n随着复制而减小,一直到0为止。如果中途失败,则n表示剩下未完成的大小。

每当装入一个段寄存器时,CPU都要根据这新的段选择码以及GDTR或LDTR的内核在相应的段描述符表中找到所选的段描述项。如果因为不管什么原因而使选择码或描述项无效或不符时,CPU就会产生一次“全面保护”异常(GP异常),当这样的异常发生在系统空间,将空选择码(0)装入一个段寄存器(除CS和SS以外)本身不会引起GP异常,而要到以后企图通过空选择码访问内存时才会引起异常(但那是回到用户空间的事)。当发生GP问题,对于CS和SS不能通过空选择码解决。只好通过do-exit( ),把当前进程杀掉,把当前进程杀了以后,内核会调度另一个进程成为的当前进程。


/从内核中可以直接访问当前进程的用户空间,所使用的虚拟地址也与当进程处于用户空间时的地址完全相同。






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值