《Linux内核原理与分析》第三周作业
實(shí)驗(yàn):基于kernel的簡(jiǎn)單的時(shí)間片輪轉(zhuǎn)多道程序內(nèi)核
1、實(shí)驗(yàn)要求
完成一個(gè)簡(jiǎn)單的時(shí)間片輪轉(zhuǎn)多道程序內(nèi)核代碼
2、實(shí)驗(yàn)過(guò)程
- 進(jìn)入實(shí)驗(yàn)樓的linux環(huán)境,打開shell,輸入以下代碼:
執(zhí)行的效果如下:
在mykernel的基礎(chǔ)上添加mypcb.h,修改mymain.c和myinterrupt.c文件,實(shí)現(xiàn)一個(gè)簡(jiǎn)單的操作系統(tǒng)內(nèi)核,實(shí)現(xiàn)效果如下:
3、mykernel時(shí)間片輪轉(zhuǎn)代碼分析
mypcb.h
本mypcb.h頭文件主要定義了程序控制塊PCB,包括:
pid:定義進(jìn)程id
state:進(jìn)程狀態(tài)標(biāo)記,-1是未運(yùn)行,0為運(yùn)行,>0為終止
stack:定義使用的堆棧
thread:定義線程
task_entry:進(jìn)程入口
next:鏈表指向下一個(gè)PCB
myinterrupt.c
#include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/tty.h> #include <linux/vmalloc.h> #include "mypcb.h"extern tPCB task[MAX_TASK_NUM]; //extern引用全局變量 extern tPCB * my_current_task; extern volatile int my_need_sched; volatile int time_count = 0;void my_timer_handler(void) //時(shí)鐘中斷觸發(fā)本函數(shù) { #if 1if(time_count%100 == 0 && my_need_sched != 1) //當(dāng)時(shí)鐘中斷發(fā)生100次,并且my_need_sched不為1時(shí),賦值為1{printk(KERN_NOTICE ">>>my_timer_handler here<<<\n");my_need_sched = 1;} time_count ++ ; #endifreturn; }void my_schedule(void) {tPCB * next; //下一進(jìn)程tPCB * prev; //當(dāng)前進(jìn)程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 */ //下一個(gè)進(jìn)程可運(yùn)行,執(zhí)行進(jìn)程切換{my_current_task = next; printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid); /* 切換進(jìn)程 */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)); }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; }本c文件中,定義了my_timer_handler和my_schedule兩個(gè)函數(shù)調(diào)用,前者是當(dāng)時(shí)鐘中斷發(fā)生100次,并且my_need_sched不為1時(shí),賦值為1,是mymain.c中my_process函數(shù)判定主動(dòng)調(diào)度的標(biāo)志;后者是執(zhí)行調(diào)度的具體過(guò)程,下面對(duì)切換進(jìn)程的匯編代碼進(jìn)行分析:
"pushl %%ebp\n\t" /* save ebp / ebp入棧
"movl %%esp,%0\n\t" / save esp / 保存當(dāng)前esp到進(jìn)程的sp中
"movl %2,%%esp\n\t" / restore esp / esp指向下一進(jìn)程
"movl $1f,%1\n\t" / save eip / 將1f存儲(chǔ)到進(jìn)程的ip中,$1f是標(biāo)號(hào)“1:\t”處,再次調(diào)度到該進(jìn)程時(shí)就會(huì)從1:開始執(zhí)行
"pushl %3\n\t" 下一進(jìn)程的ip入棧
"ret\n\t" / restore eip / eip指向下一進(jìn)程的起始地址
"1:\t" / next process start here */ 下一進(jìn)程從此處開始執(zhí)行
"popl %%ebp\n\t" 執(zhí)行完后出棧釋放空間
: "=m" (prev->thread.sp),"=m" (prev->thread.ip) 分別對(duì)于上面的%0,%1
: "m" (next->thread.sp),"m" (next->thread.ip) 分別對(duì)應(yīng)上面的%2,%3
mymain.c
#include <linux/types.h> #include <linux/string.h> #include <linux/ctype.h> #include <linux/tty.h> #include <linux/vmalloc.h> #include "mypcb.h"tPCB task[MAX_TASK_NUM]; //PCB的數(shù)組task tPCB * my_current_task = NULL; //當(dāng)前task指針 volatile int my_need_sched = 0; //是否需要調(diào)度void my_process(void); //my_process函數(shù)聲明void __init my_start_kernel(void) //mykernel內(nèi)核代碼的入口 {int pid = 0;int i;/* 初始化0號(hào)進(jìn)程*/task[pid].pid = pid;task[pid].state = 0;/* -1 unrunnable, 0 runnable, >0 stopped */task[pid].task_entry = task[pid].thread.ip = (unsigned long)my_process;task[pid].thread.sp = (unsigned long)&task[pid].stack[KERNEL_STACK_SIZE-1];task[pid].next = &task[pid];/*fork其他進(jìn)程 */for(i=1;i<MAX_TASK_NUM;i++){memcpy(&task[i],&task[0],sizeof(tPCB));task[i].pid = i;task[i].state = -1;task[i].thread.sp = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-1];task[i].next = task[i-1].next;task[i-1].next = &task[i];}/* 用task[0]開始0號(hào)進(jìn)程 */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*/); } 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) //判斷是否需要調(diào)度{my_need_sched = 0;my_schedule(); //這是一個(gè)主動(dòng)調(diào)度}printk(KERN_NOTICE "this is process %d +\n",my_current_task->pid);} } }本c文件中,有my_start_kernel和my_process兩個(gè)函數(shù),其中,前者為mykernel內(nèi)核代碼的入口函數(shù),后者為進(jìn)程的入口函數(shù),進(jìn)程在運(yùn)行中輸出當(dāng)前進(jìn)程號(hào),并通過(guò)my_need_sched變量判斷是否需要調(diào)度。
其中對(duì)0號(hào)進(jìn)程的啟動(dòng)匯編代碼進(jìn)行分析:
"movl %1,%%esp\n\t" /* set task[pid].thread.sp to esp / 將當(dāng)前進(jìn)程0的sp賦給esp
"pushl %1\n\t" / push ebp / 進(jìn)程0的sp入棧
"pushl %0\n\t" / push task[pid].thread.ip / 進(jìn)程0的ip入棧
"ret\n\t" / pop task[pid].thread.ip to eip / 將進(jìn)程0的ip賦給eip
"popl %%ebp\n\t" 執(zhí)行完其他進(jìn)程,回到0號(hào)進(jìn)程,出棧
:
: "c" (task[pid].thread.ip),"d" (task[pid].thread.sp) / input c or d mean %ecx/%edx*/ 輸入,將0號(hào)進(jìn)程的ip、sp值分別存入ecx、edx寄存器中,分別對(duì)應(yīng)上面的%0,%1
4、問(wèn)題與總結(jié)
本次實(shí)驗(yàn)沒(méi)有遇到什么重大的問(wèn)題,但是小毛病犯了一堆,比如在將代碼拷入實(shí)驗(yàn)樓linux環(huán)境的vim中時(shí),實(shí)驗(yàn)樓的粘貼板不知為何復(fù)制粘貼會(huì)缺失一段代碼,后在編譯c文件的時(shí)候總是報(bào)錯(cuò),這個(gè)問(wèn)題找了好久,后來(lái)發(fā)現(xiàn)是粘貼板粘貼的代碼缺失。還有一個(gè)是在make時(shí)找不到文件,后來(lái)發(fā)現(xiàn)修改代碼是在/mykernel目錄下進(jìn)行修改的,make編譯內(nèi)核需要在LinuxKernel/linux-3.9.4目錄下進(jìn)行,需要返回上一級(jí)菜單進(jìn)行make。
總共來(lái)講,本周各種事情比較多,學(xué)習(xí)的計(jì)劃一拖再拖,推遲了好久才完成,以后一定要合理分配時(shí)間,這一點(diǎn)尤為重要。
還有,學(xué)習(xí)要認(rèn)真仔細(xì),盡量避免因?yàn)榉傅图?jí)錯(cuò)誤而白白消耗大量學(xué)習(xí)時(shí)間。
轉(zhuǎn)載于:https://www.cnblogs.com/intoxication/p/9866849.html
總結(jié)
以上是生活随笔為你收集整理的《Linux内核原理与分析》第三周作业的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: React Native StyleSh
- 下一篇: python---pandas.merg