标签:
第一种分类:
I/O-bound:频繁的进行I/O,通常会花费很多时间等待I/O操作的完成。
CPU-bound:计算密集型,需要大量的CPU时间进行计算。
第二种分类:
批处理进程(batch process):不必和用户交互,通常在后台进行;不必很快的响应;典型例子:编译程序、科学计算
实时进程(real-time process):有实时要求、不应被优先级低的进程阻塞;响应时间短、要稳定;典型例子:视频/音频、机械控制
交互式进程(interactive process):需要和用户交互,因此要花很多时间等待用户操作;响应时间快;典型例子:shell、文本编辑器、图形应用程序。
中断处理过程(包括时钟中断、I/O中断、系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule();
内核线程(只有内核态没有用户态的特殊进程)可以直接调用schedule()进行进程切换,也可以在中断处理过程中进行调度,也就是说内核线程作为一类的特殊的进程可以主动调度,也可以被动调度;
用户态进程无法实现主动调度(只能被动调度),仅能通过陷入内核态后的某个时机点进行调度,即在中断处理过程中进行调度。
为了控制进程的执行,内核必须有能力挂起正在CPU上执行的进程,并恢复以前挂起的某个进程的执行,这叫做进程切换、任务切换、上下文切换。
挂起正在CPU上执行的进程,与中断时保存现场是不同的,中断前后是在同一个进程上下文中,只是由用户态转向内核态执行;进程上下文切换时两个进程在切换。
进程上下文包含了进程执行需要的所有信息
schedule()函数选择一个新的进程来运行,并调用context_switch进行上下文的切换,这个宏调用switch_to来进行关键上下文切换。
#define switch_to(prev, next, last) do { /* * Context-switching clobbers all registers, so we clobber * them explicitly, via unused output variables. * (EAX and EBP is not listed because EBP is saved/restored * explicitly for wchan access and EAX is the return value of * __switch_to()) */ unsigned long ebx, ecx, edx, esi, edi; 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 $1f,%[prev_ip]\n\t" /* save EIP */ "pushl %[next_ip]\n\t" /* restore EIP */ __switch_canary "jmp __switch_to\n" /* regparm call */ "1:\t" "popl %%ebp\n\t" /* restore EBP */ "popfl\n" /* restore flags */ /* output parameters */ //thread.sp内核堆栈的栈底 : [prev_sp] "=m" (prev->thread.sp), //thread.ip进程的eip [prev_ip] "=m" (prev->thread.ip), "=a" (last), /* clobbered output registers: */ "=b" (ebx), "=c" (ecx), "=d" (edx), "=S" (esi), "=D" (edi) __switch_canary_oparam /* input parameters: */ //next->thread.sp下一个进程的内核堆栈的栈底 : [next_sp] "m" (next->thread.sp), //next->thread.ip下一个进程执行的起点 [next_ip] "m" (next->thread.ip), /* regparm parameters for __switch_to(): */ [prev] "a" (prev), [next] "d" (next) __switch_canary_iparam : /* reloaded segment registers */ "memory"); } while (0)
正在运行的用户态进程X切换到运行用户态进程Y的过程
内核是各种中断处理过程和内核线程的集合,内核态的部分共享,是一样的。
典型的linux架构
main函数中有个gets()以获取字符串,执行gets这个系统调用会陷入到内核态,在等待键盘输入的过程,CPU会调度到其他进程,同时,在执行其他进程的过程中,会等待输入。当在键盘上敲击字符时,会产生IO中断给CPU,CPU进行中断处理,在中断处理过程中,接受了一个键盘输入,进而判断是X进程在等待键盘输入。开始时,x进程执行到gets陷入到内核态时,若没有键盘输入会进入阻塞态,有了键盘输入后,会把X进程设为就绪态,进程管理切换到进程X,gets系统调用获得了读入的数据,返回到用户态,继续执行下一条指令。
标签:
原文地址:http://www.cnblogs.com/boyiliushui/p/5489851.html