系统调用的过程

  系统有些高特权的操作,比如访问 IO 设备,修改内核状态,修改其他程序,在rings模型下,只有rings 0才能做得到。用户程序(通常是ring3)在自己的地址空间里面,是没有办法看到这些资源,也就无法修改它们。这时候用户程序就需要request service,发出软(件)中断,让程序trapped 进内核态(通过int 0x80 指令,实际上这不仅仅是进程的状态转换,也是进程的状态转换)。实际上此时的控制权已经交给内核了,内核可以在自己的内核地址空间里面,使用高特权操作,特权操作做完了以后,控制权才交回给用户程序。这个过程就成为syscall。x86 虽然有四层 ring,但通常只使用了0和3层ring

此处输入图片的描述

  系统通常提供API或者lib来提供syscall的能力。比如在 Unix-Like系统里,就是glibclib提供的函数,通常被称为Wrapper Function

系统调用的代价在哪里

  每次产生系统调用,程序的上下文通常会产生切换,CPU必然是要把进程状态寄存器里面往内存里塞,再把其他进程的上下文从内存里往寄存器里面塞。即使只是单进程做系统调用也如此,因为系统调用自己也有特殊的上下文,需要从内存里往寄存器塞。然后系统调用执行完了以后,原本进程的上下文,又要从内存里塞回寄存器。再加上程序的进程切换会让硬件体系结构缓存失效,上下文切换回来以后,有些缓存又要重新加载。这种种的因果,必然会增加内存查找(memory look up)次数。

  而且有些系统调用,会涉及IO操作,这容易让 CPU 进入一种阻塞状态,浪费 CPU 时间。这种阻塞状态是不会(主动)出让 CPU 的。

相关参考资料:

  1. https://www.quora.com/Why-are-system-calls-expensive-in-operating-systems
  2. http://www.tldp.org/LDP/khg/HyperNews/get/syscall/syscall86.html
  3. http://web.yl.is.s.u-tokyo.ac.jp/~tosh/kml/
  4. https://en.wikipedia.org/wiki/System_call#Categories_of_system_calls