标签:
朱秀秀 + 原创作品转载请注明出处 + 《Linux内核分析》MOOC课程http://mooc.study.163.com/course/USTC-1000029000
通过演示完成一个简单的时间片轮转多道程序内核代码,大致上了解了计算机操作系统的进程之间的切换原理,我的理解是:进程之间的切换时间要受到时间片的长短的影响,时间片越长,那么不同进程之间的切换就会相隔的时间越长,切换的频率就会下降,尤其是进程的启动与进程的切换,是操作系统管理进程中的重要步骤,下面这段代码是用来启动0进程的:
pid = 0; | |
my_current_task = &task[pid]; | |
asm volatile( | |
"movl %1,%%esp\n\t" /* set task[pid].thread.sp to esp */ | |
"pushl %1\n\t" /* push ebp */ | |
"pushl %0\n\t" /* push task[pid].thread.ip */ | |
"ret\n\t" /* pop task[pid].thread.ip to eip */ | |
"popl %%ebp\n\t" | |
: | |
: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) /* input c or d mean %ecx/%edx*/ | |
); |
利用了C语言中嵌套汇编代码的方法:首先是把0进程的sp压入esp,把ebp、0进程的ip压栈,紧接着把0进程的ip弹出到eip,这样就开启了0进程。
接下来这段程序是对调度机制的处理,根据调度标识my_need_sched来决定是否进行进程调度,如果my_need-sched=1,那么就表示在完成一个时间片:10000000时,就进行一次调度,并把相应的调度标示符置为0.
void my_process(void) | |
{ | |
int i = 0; | |
while(1) | |
{ | |
i++; | |
if(i%10000000 == 0) | |
{ | |
printk(KERN_NOTICE "this is process %d -\n",my_current_task->pid); | |
if(my_need_sched == 1) | |
{ | |
my_need_sched = 0; | |
my_schedule(); | |
} | |
printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid); | |
} | |
} | |
} |
还有就是关于转向另一个进程的代码:
void my_schedule(void) | |
{ | |
tPCB * next; | |
tPCB * prev; | |
if(my_current_task == NULL | |
|| my_current_task->next == NULL) | |
{ | |
return; | |
} | |
printk(KERN_NOTICE ">>>my_schedule<<<\n"); | |
/* schedule */ | |
next = my_current_task->next; | |
prev = my_current_task; | |
if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */ | |
{ | |
/* switch to next process */ | |
asm volatile( | |
"pushl %%ebp\n\t" /* save ebp */ | |
"movl %%esp,%0\n\t" /* save esp */ | |
"movl %2,%%esp\n\t" /* restore esp */ | |
"movl $1f,%1\n\t" /* save eip */ | |
"pushl %3\n\t" | |
"ret\n\t" /* restore eip */ | |
"1:\t" /* next process start here */ | |
"popl %%ebp\n\t" | |
: "=m" (prev->thread.sp),"=m" (prev->thread.ip) | |
: "m" (next->thread.sp),"m" (next->thread.ip) | |
); | |
my_current_task = next; | |
printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid); | |
} | |
else | |
{ | |
next->state = 0; | |
my_current_task = next; | |
printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid); | |
/* switch to new process */ | |
asm volatile( | |
"pushl %%ebp\n\t" /* save ebp */ | |
"movl %%esp,%0\n\t" /* save esp */ | |
"movl %2,%%esp\n\t" /* restore esp */ | |
"movl %2,%%ebp\n\t" /* restore ebp */ | |
"movl $1f,%1\n\t" /* save eip */ | |
"pushl %3\n\t" | |
"ret\n\t" /* restore eip */ | |
: "=m" (prev->thread.sp),"=m" (prev->thread.ip) | |
: "m" (next->thread.sp),"m" (next->thread.ip) | |
); | |
} | |
return; | |
} |
以上这段代码分别考虑了转向已经存在的进程和转向从来没有执行过的进程的情况,两者只相差一条汇编语句,都是把next->thread.ip的值存放进eip中,这样就开启了下一条进程或者是新的进程。具体的实验截图为:www.shiyanlou.com/u/NTY0MzE5MDQ2MjI3/result/659
标签:
原文地址:http://www.cnblogs.com/crystal-challenging/p/4338148.html