一個(gè)簡(jiǎn)單的時(shí)間片輪轉(zhuǎn)多道程序內(nèi)核代碼

實(shí)驗(yàn):

首先盛泡,通過使用實(shí)驗(yàn)樓虛擬機(jī)shell搭建好虛擬x86平臺(tái)

然后傍菇,查看myinterrupt.c代碼

執(zhí)行mytimerhandler每次時(shí)鐘中斷時(shí)調(diào)用一次台谊,在中斷處理時(shí)做中斷操作

查看mymain.c代碼

執(zhí)行mystartkernel執(zhí)行操作系統(tǒng)入口爹殊,循環(huán)在每100000次打印一次執(zhí)行信息

構(gòu)造一個(gè)簡(jiǎn)單的操作系統(tǒng)內(nèi)核

mypcb.h

#define MAX_TASK_NUM        4
#define KERNEL_STACK_SIZE   1024*2 # unsigned long
/* CPU-specific state of this task */
struct Thread {
    unsigned long       ip;
    unsigned long       sp;
};

typedef struct PCB{
    int pid;
    volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
    unsigned long stack[KERNEL_STACK_SIZE];
    /* CPU-specific state of this task */
    struct Thread thread;
    unsigned long   task_entry;
    struct PCB *next;
}tPCB;

void my_schedule(void);

分析:
在頭文件中
-定義了兩個(gè)變量,MAX_TASK_NUM最大任務(wù)數(shù)嫁怀,和KERNEL_STACK_SIZE用來標(biāo)椛杈瑁空間大小
-定義了一個(gè)Tread結(jié)構(gòu),中有兩個(gè)變量ip和sp塘淑,其功能是保護(hù)現(xiàn)場(chǎng)
-定義了一個(gè)PCB結(jié)構(gòu)萝招,即進(jìn)程控制塊,中有六個(gè)變量
--pid進(jìn)程標(biāo)識(shí)
--state狀態(tài)存捺,1為不可運(yùn)行槐沼,0為可運(yùn)行,>0為停止
--stack[KERNEL_STACK_SIZE]定義了一個(gè)和進(jìn)程控制塊自己的棸浦危空間
--thread一個(gè)Tread結(jié)構(gòu)
--task_entry一個(gè)任務(wù)入口點(diǎn)
--next為下一個(gè)PCB結(jié)構(gòu)的指針
-最后定義了一個(gè)my_schedule函數(shù)

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];
tPCB * my_current_task = NULL;
volatile int my_need_sched = 0;

void my_process(void);


void __init my_start_kernel(void)
{
    int pid = 0;
    int i;
    /* Initialize process 0*/
    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 more process */
    for(i=1;i<MAX_TASK_NUM;i++)
    {
        memcpy(&task[i],&task[0],sizeof(tPCB));
        task[i].pid = i;
        task[i].thread.sp = (unsigned long)&task[i].stack[KERNEL_STACK_SIZE-1];
    *(task[i].thread.sp - 1) = task[i].thread.sp;
    task[i].thread.sp -= 1;
        task[i].next = task[i-1].next;
        task[i-1].next = &task[i];
    }
    /* 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*/
    );
}   
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);
        }     
    }
}

分析:
-定義了一個(gè)最大任務(wù)數(shù)為大小的PCB結(jié)構(gòu)數(shù)組
-my_current_task=NULL岗钩,用來指向當(dāng)前PCB的指針
-my_need_sched=0,用來記錄所需schedule數(shù)量
-定義了一個(gè)my_start_kernel函數(shù)
--首先對(duì)0號(hào)進(jìn)程進(jìn)行初始化具滴,設(shè)置其標(biāo)號(hào)凹嘲、狀態(tài)前后關(guān)系、和鏈表關(guān)系變量等
--然后用for循環(huán)對(duì)1號(hào)及其之后變量依次進(jìn)行初始化以fork更多進(jìn)程
--最后通過內(nèi)嵌匯編代碼開始運(yùn)行0號(hào)進(jìn)程塊
---具體操作為將0進(jìn)程中stread.sp值存入esp构韵,當(dāng)前代碼地址入棧,保存現(xiàn)場(chǎng)
-定義了一個(gè)my_process函數(shù)
--用一個(gè)循環(huán)在操作控制臺(tái)顯示進(jìn)程正在運(yùn)行的信息
--也可以用來進(jìn)行進(jìn)程具體操作

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 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 
        || 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 */
    {        
        my_current_task = next; 
        printk(KERN_NOTICE ">>>switch %d to %d<<<\n",prev->pid,next->pid);  
        /* 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)
        ); 
    }  
    return; 
}

分析:
-定義了全局task[MAX_TASK_NUM]一個(gè)PCB數(shù)組
-定義了全局my_current_task一個(gè)PCB指針
-定義了全局整型my_need_sched
-定義了time_count = 0趋艘,一個(gè)計(jì)時(shí)器
-定義了一個(gè)my_time_handler函數(shù)
--該函數(shù)每隔1000ms產(chǎn)生一個(gè)中斷疲恢,并置my_need_sched為1
--用來為my_process函數(shù)調(diào)用my_schedule函數(shù)創(chuàng)造機(jī)會(huì)
-定義了一個(gè)my_schedule函數(shù)
--首先定義兩個(gè)PCB指針next和prev
--若此時(shí)沒有當(dāng)前需要執(zhí)行的進(jìn)程了,即返回
--開始設(shè)置next和prev指針
--此時(shí)開始判定條件
---如果next所指PCB的狀態(tài)為0瓷胧,則切換至next所指PCB開始執(zhí)行
---如果next所指PCB狀態(tài)不為0显拳,則切換至一個(gè)新的PCB開始執(zhí)行
---切換PCB執(zhí)行的動(dòng)作通過內(nèi)嵌匯編代碼來保存現(xiàn)場(chǎng)以便執(zhí)行完成之后恢復(fù)現(xiàn)場(chǎng)

總結(jié):
mypcb.h提供了時(shí)間片輪轉(zhuǎn)進(jìn)程控制塊所需數(shù)據(jù)結(jié)構(gòu),mymain.c對(duì)進(jìn)程進(jìn)行初始化并提供了進(jìn)程開始執(zhí)行的入口搓萧,
myinterrupt.c產(chǎn)生中斷信號(hào)并提供了進(jìn)程管理的核心功能杂数。
其中需要嵌入?yún)R編代碼來完成進(jìn)程切換動(dòng)作宛畦,說明中斷保存現(xiàn)場(chǎng)工作需要由cpu和內(nèi)核代碼共同實(shí)現(xiàn)

王瀟洋

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市揍移,隨后出現(xiàn)的幾起案子次和,更是在濱河造成了極大的恐慌,老刑警劉巖那伐,帶你破解...
    沈念sama閱讀 221,888評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件踏施,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡罕邀,警方通過查閱死者的電腦和手機(jī)畅形,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,677評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诉探,“玉大人日熬,你說我怎么就攤上這事∩隹瑁” “怎么了碍遍?”我有些...
    開封第一講書人閱讀 168,386評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)阳液。 經(jīng)常有香客問我怕敬,道長(zhǎng),這世上最難降的妖魔是什么帘皿? 我笑而不...
    開封第一講書人閱讀 59,726評(píng)論 1 297
  • 正文 為了忘掉前任东跪,我火速辦了婚禮,結(jié)果婚禮上鹰溜,老公的妹妹穿的比我還像新娘虽填。我一直安慰自己,他們只是感情好曹动,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,729評(píng)論 6 397
  • 文/花漫 我一把揭開白布斋日。 她就那樣靜靜地躺著,像睡著了一般墓陈。 火紅的嫁衣襯著肌膚如雪恶守。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,337評(píng)論 1 310
  • 那天贡必,我揣著相機(jī)與錄音兔港,去河邊找鬼。 笑死仔拟,一個(gè)胖子當(dāng)著我的面吹牛衫樊,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,902評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼科侈,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼载佳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起臀栈,我...
    開封第一講書人閱讀 39,807評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蔫慧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后挂脑,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體藕漱,經(jīng)...
    沈念sama閱讀 46,349評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,439評(píng)論 3 340
  • 正文 我和宋清朗相戀三年崭闲,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了肋联。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,567評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刁俭,死狀恐怖橄仍,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牍戚,我是刑警寧澤侮繁,帶...
    沈念sama閱讀 36,242評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站如孝,受9級(jí)特大地震影響宪哩,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜第晰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,933評(píng)論 3 334
  • 文/蒙蒙 一锁孟、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧茁瘦,春花似錦品抽、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,420評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腔稀,卻和暖如春盆昙,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背烧颖。 一陣腳步聲響...
    開封第一講書人閱讀 33,531評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工弱左, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人炕淮。 一個(gè)月前我還...
    沈念sama閱讀 48,995評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像跳夭,于是被迫代替她去往敵國(guó)和親涂圆。 傳聞我的和親對(duì)象是個(gè)殘疾皇子们镜,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,585評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 網(wǎng)易云課堂《Linux內(nèi)核分析》作業(yè) 實(shí)驗(yàn)?zāi)康模?運(yùn)行并分析一個(gè)精簡(jiǎn)的操作系統(tǒng)內(nèi)核,理解操作系統(tǒng)是如何工作的 實(shí)驗(yàn)...
    aapu閱讀 829評(píng)論 0 2
  • 又來到了一個(gè)老生常談的問題润歉,應(yīng)用層軟件開發(fā)的程序員要不要了解和深入學(xué)習(xí)操作系統(tǒng)呢模狭? 今天就這個(gè)問題開始,來談?wù)劜?..
    tangsl閱讀 4,134評(píng)論 0 23
  • 得到幫助之人手持鐮刀踩衩, 曾經(jīng)嬉戲的伙伴往后站嚼鹉。 只有我一個(gè)人佇立于此, 忍不住地開始傷感驱富, 什么是正義什么叫公平锚赤,...
    心理鹽水Z閱讀 266評(píng)論 0 1
  • 木人曰:你對(duì)我的好,我知道多少褐鸥,我想對(duì)你好线脚,只是做不好。-----《曖之傷叫榕,殤之愛》
    木人石心兩點(diǎn)水閱讀 187評(píng)論 0 2
  • 我一直覺得我是一個(gè)果斷的人浑侥,做事從不拖拉,在工作中確實(shí)也是這樣行事晰绎。聽很多人說過寓落,他們第一次見到我時(shí),也會(huì)覺得我很...
    不自閱讀 195評(píng)論 0 0