Linux内核如何“监听” C库?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Linux内核如何“监听” C库?相关的知识,希望对你有一定的参考价值。
我正试图为Linux内核和用户空间中的工作原理建立一个“全局”,我很困惑。我知道用户空间利用系统调用与内核“对话”,但是我不知道如何。我试图阅读C库和内核源代码,但是它们很复杂并且不容易理解。我也读过几本关于操作系统的概念性事实的书,例如管理进程,内存,设备,但是它们并不能使“转换”(用户空间->内核)变得清晰。那么,用户空间和内核空间之间的转换究竟发生在哪里? C库如何运行计算机中运行的Linux内核中的代码?
打个比方:假设有一所房子。房子被锁了。打开房子的钥匙在房子里面。屋子里只有一个人,内核。用户空间是试图进入房屋的人。我的问题是:内核如何知道房子外面有人要这个钥匙,以及哪种机制可以用那个钥匙打开房子?
这很简单-人们可以使用门铃让内核知道它在外面等着。在我们的情况下,这个门铃通常是特殊的CPU异常,软件中断或允许用户空间应用程序使用且内核可以处理的专用指令。
所以过程是这样的:
- 首先,您需要知道系统电话号码。每个系统调用都有其唯一编号,内核内部有一个表,用于将这些编号映射到特定功能。每个体系结构都有不同的表,但表的数目相同。在两种不同的体系结构上,可能映射执行不同的系统调用。
- 然后您设置参数。这也是特定于体系结构的,但与在常规函数调用之间传递参数没有太大区别。通常,您会将参数放在特定的[[CPU寄存器中。在此体系结构的ABI中对此进行了描述。 然后输入syscall。根据体系结构,这可能意味着导致某些异常或使用专用的CPU指令。
- 内核具有特殊的处理程序功能,该功能在调用syscall时以内核模式运行。它将暂停进程执行,存储特定于该进程的所有信息(称为
context switch
),读取syscall编号和参数并调用适当的syscall例程。它还将确保将返回值放在适当的位置,以供用户空间读取,并在完成syscall例程(恢复其上下文)后安排回退进程。
x86_64上调用syscall,可以在sysenter
寄存器中使用带有syscall编号的%rax
指令。使用寄存器(如果我没记错的话)传递参数%rdi
,%rsi
,%rdx
,%rcx
,%r8
和%r9
。
int 0x80
指令)。再次,在%rax
寄存器中指定系统调用号,然后将参数转到(同样,如果我没记错的话)%ebx
,%ecx
,%edx
,%esi
,%edi
,%ebp
。 >ARM非常相似-您将使用“主管调用”指令(SVC #0
)。您的系统调用号将进入r7
寄存器,所有参数将进入寄存器r0-r6
,并且系统调用的返回值将存储在r0
中。
以上是关于Linux内核如何“监听” C库?的主要内容,如果未能解决你的问题,请参考以下文章
20135239 益西拉姆 linux内核分析 使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用