系统调用为什么昂贵
系统调用的过程
系统有些高特权的操作,比如访问 IO 设备,修改内核状态,修改其他程序,在rings模型下,只有rings 0
才能做得到。用户程序(通常是ring3
)在自己的地址空间里面,是没有办法看到这些资源,也就无法修改它们。这时候用户程序就需要request service
,发出软(件)中断,让程序trapped
进内核态(通过int 0x80 指令,实际上这不仅仅是进程的状态转换,也是进程的状态转换)。实际上此时的控制权已经交给内核了,内核可以在自己的内核地址空间里面,使用高特权操作,特权操作做完了以后,控制权才交回给用户程序。这个过程就成为syscall
。x86 虽然有四层 ring,但通常只使用了0和3层ring。
系统通常提供API
或者lib
来提供syscall
的能力。比如在 Unix-Like
系统里,就是glibc
。lib
提供的函数,通常被称为Wrapper Function
。
系统调用的代价在哪里
每次产生系统调用,程序的上下文通常会产生切换,CPU必然是要把进程状态寄存器里面往内存里塞,再把其他进程的上下文从内存里往寄存器里面塞。即使只是单进程做系统调用也如此,因为系统调用自己也有特殊的上下文,需要从内存里往寄存器塞。然后系统调用执行完了以后,原本进程的上下文,又要从内存里塞回寄存器。再加上程序的进程切换会让硬件体系结构缓存失效,上下文切换回来以后,有些缓存又要重新加载。这种种的因果,必然会增加内存查找(memory look up)次数。
而且有些系统调用,会涉及IO操作,这容易让 CPU 进入一种阻塞状态,浪费 CPU 时间。这种阻塞状态是不会(主动)出让 CPU 的。
相关参考资料:
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.