linux/kernel目录。
该目录下代码从功能上可分为三类,一类是硬件(异常)中断处理程序文件,一类是系统调用服务处理程序文件,还有进程调度等通用功能。
1. 中断处理程序
主要两个文件:asm.s和traps.c。asm.s实现大部分硬件异常所引起的中断的汇编语言处理程序。traps.c则实现了asm.s的中断处理过程中调用的C函数。另外几个硬件中断处理过程在文件sys_call.s和mm/page.s中实现。关于PC中825A可编程中断控制芯片见其他章节。
在用户程序(进程)将控制权交给中断处理程序前,CPU会首先将至少12字节(EFLAGS、CS和EIP)信息压入中断处理程序的堆栈中,即进程的内核态栈中(这不是任务切换,只是控制权转移,详细见Assembly相应内容!!!)。见图8-2a所示,这与一个远调用(段间子程序调用)类似。CPU会将代码段选择符CS和返回地址的偏移值压入堆栈。另一个与段间调用相似地方是将信息压入到目的代码(中断处理程序代码)的堆栈上,而不是被中断代码的堆栈中。
若优先级变化,例如从用户级改变到内核系统级,CPU还会将原代码的堆栈段值和堆栈指针压入中断程序的堆栈中。但内核初始化完成后,内核代码执行使用的是进程的内核态栈,而被中断代码的堆栈当然也就是指进程的用户态堆栈了。所以发生中断时,中断处理过程使用的是进程的内核态堆栈。另外,CPU还总将EFLAGS内容压入隧站。
asm.s主要涉及对Intel保留中断int0~int16的处理,其余保留的中断int17~int31由Intel保留。Linux系统调用中断int128(0x80)处理将在kernel/sys_call.s给出。
有些异常的中断,CPU内部产生一个出错码压入堆栈(异常中断int8和int10~int14),如图8-2b,而其他中断并不带有这个出错码,因此,asm.s中会根据是否携带出错码将中断分为两类处理。但处理流程还是一样。
一个硬件异常引起的中断处理过程如图8-3。
2. 系统调用处理相关程序
Linux中应用调用内核的功能是通过中断调用int 0x80进行的,寄存器eax放调用号,若带参数,ebx、ecx和edx用于存放调用参数。因此该中断调用被称为系统调用。实现系统调用相关文件包括sys_call.s、fork.c、signal.c、sys.c和exit.c文件。
sys_call.s类似于硬件中断处理中asm.s的作用,另外还对时钟中断和硬盘、软盘中断进行处理。fork.c提供了两个C处理函数:find_empty_process()和copy_process()。signal.c还提供了一个处理有关进程信号的函数do_gignal(),在系统调用中断过程中被调用。另外还有4个系统调用sys_xxx()函数。
sys.c和exit.c程序实现了一些sys_xxx()系统调用函数。这都是相应系统调用所需的处理函数。
3. 其他通用类程序
schedule.c、mktime.c、panic.c、printk.c和vsprintf.c。
schedule.c包含内核的核心调度程序,用于对进程的执行进行切换或改变执行状态。另外还有系统时钟中断和软盘驱动器定时函数。
mktime.c仅有一个内核使用的时间函数mktime(),仅在init/main.c中被调用一次。
panic.c包含一个panic()函数,用于在内核运行出错时显示出错信息并停机。
printk.c和vsprintf.c是内核显示信息的支持程序,实现内核专用显示函数printk()和字符串格式化输出函数vsprintf()。