进程上下文相关代码分析:我们怎么把当前进程切换到next进程,为了控制进程的执行,并回复以前挂起的某个进程的执行,这叫做进程切换,任务切换。
挂起正在CPU上执行的进程,与中断时保存现场是不同的,中断前后是在同一个进程上下文中,只是由用户态转向内核态执行
进程上下文包含了进程执行所需要的所有信息。
用户地址空间:包括程序代码,数据,用户堆栈等
控制信息:进程描述符,内核堆栈等
硬件上下文(注意中断也要保存硬件上下文只是保存的方法不同)
schedule()函数选择一个新的进程来运行,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换
next=pick_next_task(rq,prev)//进程调度算法都封装这个函数内部
context_switch(rq,prev,next)//进程上下文切换
switch_to利用了prev和next两个参数;prev指向当前进程,next指向被调度的进程
我们了解计算器是怎么工作的,知道修改eip,堆栈还有其他的一些寄存器,switch_to里面最关键的代码时汇编.
asm volatile("pushfl\n\t" /save flags/
"pushl %%ebp\n\t" /save EBP/
"movl %%esp,%[prev_sp]\n\t" /save ESP/
"movl %[next_sp],%%esp\n\t" /restore ESP/
"movl $lf,%[prev_ip]\n\t" /save EIP/
"pushl %[next_ip]\n\t" /retore EIP/
_switch_canary
"jmp _switch_to\n" /regparm call/
"1:\t"
"popl %%ebp\n\t" /retore EBP/
"popfl\n" /retore flags/
Linux系统的一般执行过程分析
这时候我们可以有了一个条件来理解linux系统的一般运行状态,其中有一个用户态进程X需要切换到用户进程Y。
从正在运行的用户态进程X切换到正在运行的用户态进程Y的过程
1.正在运行的用户态进程X
2.发生中断——save cs:eip/esp/eflags(current)to kernel stack,then load cs:eip(entry of a specific ISR)and ss:esp(point to kernel stack)
3.SAVE_ALL//保存现场
4.中断处理过程中或中断返回前调用了schedule(),其中的switch_to做了关键的进程上下文切换
5.标号1之后开始运行用户态进程Y(这里Y曾经通过以上步骤被切换出去过因此可以从标号1继续执行)
6.restore-all//恢复现场
7.iret -pop cs:eip/ss:eip/eflags from kernel stack
8.继续运行用户态进程Y
Linux系统执行过程中的几个特殊情况:
几种特殊情况
通过中断处理过程中的调度时机,用户态进程与内核线程之间互相切换和内核线程之间互相切换,与最一般的情况非常类似,只是内核线程运行过程中发生中断没有进程用户态和内核态的转换
内核线程主动调用schdule(),只有进程上下文的切换,没有中断上下文的切换,与最一般的情况略简略
创建子进程的系统调用在子进程中的执行起点及返回用户态,如fork;
加载一个新的可执行程序后返回到用户态的情况,如execve;
Linux操作系统架构概览
我们在这里总结一下这个课学习的内容:
任何计算机系统都包含一个基本的程序集合,称为操作系统
-内核(进程管理,进程调度,进程间通讯机制,内存管理,中断异常处理,文件系统,I/O系统,网络部分)
-其它程序(例如函数库,shell程序、系统程序等等)
操作系统的目的
-与硬件交互,管理所有的硬件资源
-为用户程序(应用程序)提供一个良好的执行环境
那么我们可以看一张图:最底层有磁盘管理,物理内存的管理,内存控制器还有控制台,这个地方它有一个Kernel Intelface to the hardware
也就是对硬件资源的管理,然后呢在上一层就是内核的实现,内核的实现也就是CPU调度,内存管理,按需调度,虚拟内存等等,还有其他的驱动,磁盘管理,文件系统等等,这些操作系统的内核,我们这门课分析的内核只是计算机操作系统里面最最关键的一些代码,实际上整个操作系统非常复杂,很多其他的部分都没有涉及。那么呢,这个地方有一个系统调用接口,这里涉及到不同的部分,基础软件也就是share共享库lib ,动态加载器这些等等等等。