Linux 系统调用权威指南
2016 年 4 月 5 日, • packagecloud (于朝阳 译)
标签:
linux
kernel
syscall
简介
什么是系统调用?
背景知识
o 硬件与软件
o 应用程序,内核与 CPU 特权级
o 中断
o 特殊模块寄存器 (MSRs)
o 通过汇编语言来执行系统调用,这不是个好主意
传统系统调用
o 自己写汇编代码来执行系统调用
o 内核部分:int $0x80 调用入口
o 从系统调用中返回 iret
快速系统调用
o 32 位快速系统调用
sysenter/ sysexit
__kernel_vsyscall 解析
自己写汇编代码来执行 sysenter 系统调用
内核部分:sysenter 调用入口
sysexit 从系统调用 sysenter 中返回
o 64 位快速系统调用
syscall/ sysret
自己写汇编代码来执行 syscall 系统调用
内核部分:syscall 调用入口
sysret 从系统调用 syscall 中返回
半手动方式调用 syscall(2)
o glibc syscall 封装解析
虚拟系统调用
o 内核vDSO
o 在内存中定位 vDSO
o glibc 中的vDSO
glibc 系统调用封装
与系统调用相关的有趣问题
o CVE-2010-3301
o 安卓 sysenter ABI 问题
结论
相关阅读
简介
这篇博文描述了 Linux 程序如何调用内核方法。
文中概述了几种不同的执行系统调用的方法,同时举例讲述了如何通过写汇编代码来执行
系统调用,以及系统调用的内核入口/出口,glibc 封装,代码错误,和其它相关信息。
什么是系统调用?
当一个应用程序调用如 open ,fork ,read ,write (或者很多其它类似方法)时,
就会用到系统调用。
系统调用就是应用程序进入内核中去完成某些任务的途径。应用程序通过系统调用来完成
一系列操作,比如:创过新进程,执行网络/文件 IO,等等。
在这个网页 man page for syscalls(2)里,可以找到所有系统调用的列表。应用程序可以
用几种不同的方法来完成系统调用,而具体的机器码则与 CPU 体系结构相关。
从应用程序开发人员的角度来看,我们大可不必关心系统调用是如何被执行的。因为我们
只需要引用合适的头文件,然后就像使用普通函数那样去调用库函数就可以了。
glibc 提供的封装代码可以让调用者不必去关心底层实现,这些封装代码会使用调用时
传入的参数来执行内核调用。
在详细解释系统调用如何执行之前,我们需要定义一些后文中出现的术语和观点。
背景知识
硬件和软件
在这篇文章中,我们有以下假设:
你用的是一个 32 位或 64 位的 Intel 或 AMD CPU 的系统。文中描述的理论对于使用其
它系统的人来说是基本相同,但是具体的代码都是以 32 位或 64 位 Intel/AMD CPU 为
例的。
你对 Linux 内核版本3.13.0 感兴趣。其它版本的代码可能是类似的,但是行号或者代
码组织方式,文件路径可能会有所不同。GitHub 上有 3.13.0 版本的内核代码可供参
考。
你对 glibc 或者基于 glibc 的其它libc 实现(比如 eglibc )感兴趣。
在这篇文章中,x86-64 指基于 x86 架构的 64 位 Intel/AMD CPU。
应用程序,内核与 CPU 特权级
应用程序(比如文本编辑器,终端程序,ssh 守护程序,等等)需要与 Linux 内核进行交
互,内核才能帮助这些应用程序完成某些应用程序自己不能做的一系 等列操作。
比如,一个应用程序需要完成某些 IO 操作( open ,read ,write