linux的组成:
内核,shell,文件系统等组成了基本的linux系统。
linux系统的主要功能有中断机制和进程管理,其中系统调用为特殊的中断。
linux的系统调用:通过int $0x80(32位)或syscall指令(64位)来触发系统调用,之后进入内核,执行对应的中断服务程序entry_INT80_32或entry_SYSCALL_64,其中syscall通过CPU内部的MRS找到存放系统调用处理入口地址,之后把相应的CPU关键的现场栈顶寄存器、指令指针寄存器、标志寄存器等保存到内核堆栈,保存现场,通过EAX寄存器传递系统调用号去执行对应的内核处理函数,处理完成后将CPU关键现场栈顶寄存器、指令指针寄存器、标志寄存器等从内核堆栈中恢复到对应寄存器中,并回到⽤户态中的下一条指令继续执行。
linux的进程管理:进程描述符task_struct中包括进程状态,堆栈,保存上下文CPU状态的thread等,还有文件系统,信号,内存,进程空间等,第一个进程为0号进程init_task,其余的所有进程均通过do_fork生成,0号进程生成1号进程kernel_init和2号进程kthreadd,分别为所有用户进程的祖先和所有内核现场的祖先。
linux的进程调度:linux进程调度的时机有1.进程状态发生变化时。2.进程时间片用完时。3.进程从系统调用返回到用户态时。4.中断处理后,进程返回到用户态时。实时进程的优先级为1-99之间,普通进程的优先级为100-139之间,数字越小,优先级越高。进程集合分为活动进程集合和过期进程集合,分别用两个指针指向,实时进程总是活动进程,进程分为批处理进程和交互进程,当批处理进程在活动进程集合时间片运行完之后,将变为过期进程,而交互进程时间片运行完之后,仍然是活动进程,除非最老的过期进程等待了很长时间,或者过期进程比交互进程优先级高,此时将活动进程移至过期进程集合中。进程切换的大致过程为,先把rbp保存在prev进程的栈中,再把rsp保存在prev进程的thread.sp中,再改变rsp,将next进程的thread.sp赋给rsp,由于不能直接对rip进行操作,通过$1f完成,把rip此时所指向的指令地址$1f保存在prev进程的thread.ip中,再将next进程的thread.ip入栈,再通过ret出栈,间接的将next进程中的thread.ip赋值给了rip,此时在rsp所指向的next的进程栈中保存着之前从next切换为其他进程时保存的rbp,继续出栈,将值赋给rbp。
进程切换的大致过程如下:
例子,I/O设备引起中断的一般过程(32位):设备的设备控制器发出中断,通过设备控制器对应的IRQ线到达中断处理器,中断处理器得到对应的中断向量,通过IDT表的得到中断向量对应的段选择符,通过段选择符在GDT中找到对应的段描述符,如果是从用户态发生中断,通过进程的tss段的信息改变ss和esp转为内核态,将原来的ss和esp存在栈中,如果是异常,将cs和eip指向这条出错指令,将eflags,cs,eip保存在栈中,如果有硬件出错码,也保存在栈中,最后将段描述符和偏移量字段装载在cs和eip中,使其指向中断处理程序入口
在用户态发生中断进入内核态时堆栈如下:
之后在中断处理程序入口,将中断向量入栈,用SAVE_ALL保存其余的寄存器,调用do_IRQ,遍历该中断号对应的所有处理例程的链表,进行中断处理,处理完成后,用jmp跳转到