前言
本文对内核中断进行概括以及讲述中断的具体实现方法在内核是怎么做的,会结合内核源码中的一些 .s 文件和 .c 文件来具体分析一下内核在中断中的实现方式。
- 学习中断的目的:
- 1、硬件的中断响应 --------> 内核驱动中的中断
- 2、系统调用的函数响应(sys_call)--------> 系统调用
- 3、自定义中断--------> 软件的软中断模式
- 4、信号中断(kill -signalnum)--------> 对了解信号的使用、创建等有很大帮助
- 5、系统的异常和错误 --------> 系统的异常获取,了解系统异常的作用
一、Linux的中断机制
1、分类
Linux的中断分为硬件中断和软件中断
- 硬中断:由电脑中主机的 8259A 类似的硬件中断控制芯片发出的中断或 ARM 中断控制器发出的中断
- 软中断:称为异常
- 第一类:CPU 自行保留的中断
- 第二类:系统调用异常
2、代码结构
汇编文件 | 对应的c文件 |
linux/kernel/asm.s | trap.c |
linux/kernel/system_call.s | fork.c signal.c exit.c sys.c |
二、中断的工作流程
1、中断的工作流程
- ①. 做 CPU 工作模式的转化
- ②. 进行寄存器的拷贝与压栈
- ③. 设置中断异常向量表
- ④. 保存正常运行的函数返回值
- ⑤. 跳转到对应的中断服务函数上运行
- ⑥. 进行模式的复原以及寄存器的复原
- ⑦. 跳转回正常工作的函数地址继续运行
2、Linux 中中断的工作流程
- ①. 将所有寄存器值入栈
- (8086中)SS寄存器、EFLAG寄存器、ESP寄存器、CS寄存器、EIP寄存器
- 错误码
- ARM 中的 r0-r15
- ②. 将异常码(中断号)入栈
- ③. 将当前的函数返回值进行入栈(为了在中断执行后能够找到在哪中断的,能够复原)
- ④. 调用对应的中断服务函数
- ⑤. 出栈函数返回值
- ⑥. 返回所有入栈的寄存器值
asm.s 和 system_call.s所做的工作是 ① ② ③ ⑤ ⑥,剩余 .c 文件所做工作是 ④
如图所示:
上图与 linux 源码对应关系如下:
中断前的处理过程,中断后的回复过程 | 中断的执行过程 | |
硬件中断的处理过程 | linux/kernel/asm.s | traps.c |
软件及系统调用的处理过程 | linux/kernel/system_call.s | fork.c signal.c exit.c sys.c |
3、中断的代码实现过程
这里仅分析asm.s 和 trap.c
中断前的处理过程,中断后的回复过程 | 中断的执行过程 | |
硬件中断的处理过程 | linux/kernel/asm.s | trap.c |
具体详细内容参考Linux内核完全注释:基于0.11内核(修正版V3.0).pdf P55~P62 和 P256~P279
链接:Linux内核完全注释:基于0.11内核(修正版V3.0).pdf
提取码:ygz8
三、内核中断体系结构
- 1、trap_init
- set_trap_gate 设置的权限较高,只能由用户程序调用
- set_system_gate 设置的权限较低,能有用户和系统所有的进程调用
- 2、system_call
- 所有的系统调用 C 函数放到了一个统一的 sys_call_table
- 系统调用的操作码
- 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, sys_break, sys_stat, sys_lseek, sys_getpid, sys_mount,
sys_umount, sys_setuid, sys_getuid, sys_stime, sys_ptrace, sys_alarm,
sys_fstat, sys_pause, sys_utime, sys_stty, sys_gtty, sys_access,
sys_nice, sys_ftime, sys_sync, sys_kill, sys_rename, sys_mkdir,
sys_rmdir, sys_dup, sys_pipe, sys_times, sys_prof, sys_brk, sys_setgid,
sys_getgid, sys_signal, sys_geteuid, sys_getegid, sys_acct, sys_phys,
sys_lock, sys_ioctl, sys_fcntl, sys_mpx, sys_setpgid, sys_ulimit,
sys_uname, sys_umask, sys_chroot, sys_ustat, sys_dup2, sys_getppid,
sys_getpgrp, sys_setsid, sys_sigaction, sys_sgetmask, sys_ssetmask,
sys_setreuid,sys_setregid }; - system_call.s ----------> Sched.c