前言
由于工作需要,个人从java栈转为了c语言栈,并需要深入学习linux内核。本系列记录一些个人学习笔记。由于Linux内核涉及内容以及知识点很多,一开始接触十分痛苦,通过反复阅读《Linux内核完全注释》一书才逐渐能够看懂源码。在理解的过程中,个人发现自上而下地探索内核,才是最适合自己的学习内核的方式。因此,本系列主要从自上而下的角度,进行笔记记录。整个系列配图及概念描述将直接引用《Linux内核完全注释》中的内容。
系统调用
本系列第一篇从系统调用开始,因为在学习的过程中,个人发现系统调用能够将各个知识点串起来,也正好借此机会对之前学习的知识点进行梳理。
什么是系统调用
系统调用(通常称为 syscalls)是 Linux 内核与上层应用程序进行交互通信的唯一接口。从对中断机制的说明可知,用户程序通过直接或间接(通过库函数)调用中断 int 0x80,并在 eax寄存器中指定系统调用功能号,即可使用内核资源,包括系统硬件资源。不过通常应用程序都是使用具有标准接口定义的 C 函数库中的函数间接地使用内核的系统调用,见下图 所示。
为了更好地理解系统调用,需要先了解中断。因此阅读时,先跳至中断章节进行阅读。
系统调用实现
在了解了中断机制及中断执行过程后,我们可以想到,只要让system_call实现类似中断机制的执行过程,就能够完成上述概念提及的功能
因此,system_call的目的是根据eax中的编号,调用系统调用表中对应的某个程序。如其代码所描述的:kernerl/system_call.s
_system_call:
cmpl $nr_system_calls-1,%eax
ja bad_sys_call
push %ds
push %es
push %fs
pushl %edx
pushl %ecx # push %ebx,%ecx,%edx as parameters
pushl %ebx # to the system call
movl $0x10,%edx # set up ds,es to kernel space
mov %dx,%ds
mov %dx,%es
movl $0x17,%edx # fs points to local data space
mov %dx,%fs
call _sys_call_table(,%eax,4)
pushl %eax
movl _current,%eax
cmpl $0,state(%eax) # state
jne reschedule
cmpl $0,counter(%eax) # counter
je reschedule
对应的表为_sys_call_table
,其在linux\sys.h中被定义
fn_ptr sys_call_table[] = {
sys_setup, sys_exit, sys_fork, sys_read,
sys_write, sys_open, sys_close, sys_waitpid, sys_creat, sys_link,
sys_unlink, sys_execve, sys_chdir, sys_time, sys_mknod, sys_chmod,
sys_chown,