姬夢馨linux
原創博客shell
《Linux內核分析》MOOC課程http://mooc.study.163.com/course/USTC-1000029000 函數
存儲程序計算機工做模型,計算機系統最最基礎性的邏輯結構;spa
函數調用堆棧,高級語言得以運行的基礎,只有機器語言和彙編語言的時候堆棧機制對於計算機來講並不那麼重要,但有了高級語言及函數,堆棧成爲了計算機的基礎功能;操作系統
enter rest
pushl %ebpcode
movl %esp,%ebpblog
leave 進程
movl %ebp,%espip
popl %ebp
函數參數傳遞機制和局部變量存儲
中斷,多道程序操做系統的基點,沒有中斷機制程序只能從頭一直運行結束纔有可能開始運行其餘程序。
2:兩個百分號 轉移字符
使用實驗樓的虛擬機打開shell
而後cd mykernel 您能夠看到qemu窗口輸出的內容的代碼mymain.c和myinterrupt.c
實驗代碼myinterrupt
及其分析
/*
* linux/mykernel/myinterrupt.c * Kernel internal my_timer_handler * Copyright (C) 2013 Mengning */ #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 tPCB * my_current_task; extern volatile int my_need_sched; volatile int time_count = 0; /* * Called by timer interrupt. * it runs in the name of current running process, * so it use kernel stack of current running process */ void my_timer_handler(void)//用於設置時間片的大小,時間片用完時設置調度標誌。 { #if 1 if(time_count%1000 == 0 && my_need_sched != 1) { printk(KERN_NOTICE ">>>my_timer_handler here<<<\n"); my_need_sched = 1; } time_count ++ ; #endif return; } void my_schedule(void) { tPCB * next; tPCB * prev; if(my_current_task == NULL //task爲空,即發生錯誤時返回 || my_current_task->next == NULL) { return; } printk(KERN_NOTICE ">>>my_schedule<<<\n"); /* schedule */ next = my_current_task->next;//把當前進程的下一個進程賦給next prev = my_current_task;//當前進程爲prev if(next->state == 0)/* -1 unrunnable, 0 runnable, >0 stopped */ { /* switch to next process */ /*若是下一個進程的狀態是正在執行的話,就運用if語句中的代碼表示的方法來切換進程*/ asm volatile( "pushl %%ebp\n\t" /* save ebp 保存當前進程的ebp*/ "movl %%esp,%0\n\t" /* save esp 把當前進程的esp賦給%0(指的是thread.sp),即保存當前進程的esp*/ "movl %2,%%esp\n\t" /* restore esp 把%2(指下一個進程的sp)放入esp中*/ "movl $1f,%1\n\t" /* save eip $1f是接下來的標號「1:」的位置,把eip保存下來*/ "pushl %3\n\t" /*把下一個進程eip壓棧*/ "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; }
內核初始化和0號進程啓動
實驗體會:
實驗步驟雖然很簡單,但過程是很複雜的,須要本身慢慢的理解,體會。理解代碼的過程是很複雜的,須要耐心和認真。
但願本身之後分析代碼的時候可以更加的細心,認真。