日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

基于时间片轮转程序分析进程调度

發(fā)布時間:2025/5/22 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于时间片轮转程序分析进程调度 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

?

?張雨梅 ??原創(chuàng)作品轉(zhuǎn)載請注明出處

《Linux內(nèi)核分析》MOOC課程http://mooc.study.163.com/course/USTC-10000

?

背景知識

? ? ? ?一般程序運行過程中都會發(fā)生中斷,發(fā)生中斷時,CPU先把當前的內(nèi)容保存,然后執(zhí)行中斷程序,中斷返回時,根據(jù)保存的內(nèi)容恢復現(xiàn)場。這次實驗用一個簡單的時間片輪轉(zhuǎn)程序分析進程調(diào)度的過程。

?

實驗過程

? ? ?使用實驗樓的虛擬機操作,實驗代碼在mykernel中找,包括3個c文件,mypcb.h,mymain.c,myinterrupt.c。

? ? ?打開實驗樓的shell,修改mykernel文件夾中的三個文件,然后make

cd LinuxKernel/linux-3.9.4 cd mykernel vi mymain.c vi myinterrupt.c vi mypcb.h cd .. make allnoconfig make

運行結(jié)果的部分截圖如下,可以看到此時進程3切換到進程0

?

代碼分析

? ? ?實驗用到三個c文件,?mypcb.h,mymain.c,myinterrupt.c。其中,

? ? ?mypcb.h的主要功能:

? ? ? ? ? 1.PCB結(jié)構(gòu)體

? ? ? ? ? 2.Thread結(jié)構(gòu)體

? ? ? ? ? 3.聲明了my_schedule函數(shù)

? ? ?mymain.c的主要功能:

? ? ? ? ? 1.my_start_kernel函數(shù)創(chuàng)建進程0,也是入口函數(shù)

? ? ? ? ? 2.復制進程

? ? ? ? ? 3.進程函數(shù)my_process,其中有my_schedule函數(shù)的調(diào)用

? ? ?myinterrupt.c的主要功能:

? ? ? ? ? 1.my_timer_handler產(chǎn)生時鐘中斷

? ? ? ? ? 2.my_schedule切換進程

?

? ? 下面分析程序的執(zhí)行過程

? ? ? ? ? mypcb.h中設置MAX_TASK_NUM的值為4,也就是共有四個進程,分別為0,1,2,3.

? ? ? ? ? 程序從my_start_kernel開始執(zhí)行,? ??

int pid = 0;int i;/* Initialize process 0*/task[pid].pid = pid;/*進程0*/task[pid].state = 0;/* -1 unrunnable, 0 runnable, >0 stopped 進程0的初始狀態(tài)為可運行 */task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;/*進程0的eip指向my_process*/task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1];/*初始時sp指向分配給進程0的堆棧的最高地址*/task[pid].next = &task[pid];/*初始進程0的下一個進程是進程0*/

? ? ? ? ? 然后復制了三個進程,注意

task[i].state = -1;/*進程1,2,3的初始狀態(tài)不可執(zhí)行*/ task[i].next = task[i-1].next;task[i-1].next = &task[i];

? ? ? ? 這兩句代碼設置了進程的切換方式,比如進程0切換到進程1,進程1切換到進程2。

? ? ? ? ?

/* start process 0 by task[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*/);

? ? ? ? ? 現(xiàn)在執(zhí)行的是進程0,這段代碼是把esp指向分配給進程0的堆棧段的最高地址,把當前ebp入棧保存,eip指向task[pid].thread.ip,也就是my_process,開始執(zhí)行my_process函數(shù)。這里ret執(zhí)行以后,轉(zhuǎn)到my_process函數(shù),"popl %%ebp\n\t"這一句不執(zhí)行。

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;/*置為0,不能進行進程調(diào)度,直到再次發(fā)生時鐘中斷置為1*/ my_schedule(); } printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid);
}

? ? ? ? ??結(jié)合my_timer_handler函數(shù)一起分析

if(time_count%1000 == 0 && my_need_sched != 1){printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");my_need_sched = 1;/*置為1*/}

? ? ? ? ?初始my_need_sched值為0,my_timer_handler函數(shù)發(fā)生時鐘中斷時,置my_need_sched值為1,my_process函數(shù)中滿足進程調(diào)度條件,調(diào)用my_schedule()。進程0的next是進程1,初始時,進程1,2,3的state均為-1,故執(zhí)行else段。也就是說初次切換到進程1,2,3時都是先執(zhí)行else段的代碼。? ?

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));}

? ? ? ? 1.state:先把進程1的state置為0,下次切換到進程1的時候,就是執(zhí)行if段。

? ? ? ? 2.ebp、esp:目前依然在進程0的堆棧中,先把進程0的ebp入棧保存,設置pre->thread.sp為進程0的當前esp,然后esp、ebp都指向進程1的esp,其被初始化為分配給進程1的堆棧的最高地址。ebp、esp值相同,因為進程1初次使用,堆棧為空。

? ? ? ? 3.eip:設置進程0的eip為$1f,用pre->thread.ip保存,表示if代碼段1:處,即下次切換到進程0時,從1:處開始執(zhí)行。eip指向eip指向進程1的eip,其被初始化為my_process。

? ? ? ? 這時即完成了進程0向進程1的切換。進程1切換進程2,進程2切換到進程3的執(zhí)行過程與之類似。

?

? ? ? ? 當進程3切換到進程0時,由于進程0已經(jīng)被執(zhí)行過一次,其state為0,此時執(zhí)行if代碼段。??

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段代碼大體過程相同,就是保存進程3的ebp,esp,eip,然后對esp,eip重新賦值。不同的是:

? ? ? ? ? 1.if沒有設置ebp的值,此時進程0的棧非空

? ? ? ? ? 2.if中設置的eip為進程0的eip,也就是執(zhí)行到1:處,注意此時是已經(jīng)轉(zhuǎn)到了進程0的堆棧中。然后執(zhí)行pop %%ebp,由于進程0的棧頂元素是進程0被中斷時保存的ebp,此時進程0的堆棧情況和被中斷時的堆棧情況一樣。

? ? ? ? ? 繼續(xù)執(zhí)行下面的代碼,是在進程0的堆棧中執(zhí)行的。

? ? ? ? ? 程序繼續(xù)運行,以后發(fā)生的進程切換執(zhí)行的都是if段代碼,和上述過程相同。

? ? ? ? ??

? ? ? ? ? 進程切換的執(zhí)行過程可以表示為

? ? ? ? ? ? ??

? ? ? ? ? ? ?另外可以看出,進程的next,prev是變化的,當前的prev進程,在以后的進程調(diào)度中,會變成next進程。

?

轉(zhuǎn)載于:https://www.cnblogs.com/icecri/p/4339641.html

總結(jié)

以上是生活随笔為你收集整理的基于时间片轮转程序分析进程调度的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。