Linux 核心 任務0的排程切換

2021-06-06 10:26:44 字數 2775 閱讀 7879

main.c中在move_to_user_mode()之後,切換到使用者模式下執行,task0然後執行fork()建立程序task1來執行init()函式。init()函式如下:

[cpp]view plain

copy

print?

void

init (

void

)    

// 下面是父程序執行的語句。wait()是等待子程序停止或終止,其返回值應是子程序的程序號(pid)。

// 這三句的作用是父程序等待子程序的結束。&i 是存放返回狀態資訊的位置。如果wait()返回值不

// 等於子程序號,則繼續等待。

if(pid > 0)  

while

(pid != wait (&i))  

/* nothing */

;  // 如果執行到這裡,說明剛建立的子程序的執行已停止或終止了。下面迴圈中首先再建立乙個子程序,

// 如果出錯,則顯示「初始化程式建立子程序失敗」的資訊並繼續執行。對於所建立的子程序關閉所有

// 以前還遺留的控制代碼(stdin, stdout, stderr),新建立乙個會話並設定程序組號,然後重新開啟

// /dev/tty0 作為stdin,並複製成stdout 和stderr。再次執行系統解釋程式/bin/sh。但這次執行所

// 選用的引數和環境陣列另選了一套(見上面165-167 行)。然後父程序再次執行wait()等待。如果

// 子程序又停止了執行,則在標準輸出上顯示出錯資訊「子程序pid 停止了執行,返回碼是i」,然後

// 繼續重試下去…,形成「大」死迴圈。

while

(1)  

if(!pid)  

while

(1)  

if(pid == wait (&i))  

break

;  printf ("/n/rchild %d died with code %04x/n/r"

, pid, i);  

sync ();  

}  _exit (0);            /* note! _exit, not exit() */

}    

init程序通過fork()產生子程序,產生的子程序開始讀取硬碟引數包括分割槽表資訊並建立虛擬盤和安裝根檔案系統裝置,開啟裝置,並執行sh程式

,當該程序異常結束,就會迴圈重試上述過程。然而程序0這時會執行到**

for(;;) pause()

處,pause()函式是系統呼叫,它也被宣告為內聯函式,通過int 0x80呼叫系統呼叫sys_pause()。

[cpp]view plain

copy

print?

intsys_pause (void

)    

該系統呼叫所做的任務就是將當前任務的執行狀態改為可中斷執行狀態,然後執行排程函式schedule()。

[cpp]view plain

copy

print?

void

schedule (void

)    

// 如果訊號點陣圖中除被阻塞的訊號外還有其它訊號,並且任務處於可中斷狀態,則置任務為就緒狀態。

// 其中'~(_blockable & (*p)->blocked)'用於忽略被阻塞的訊號,但sigkill 和sigstop 不能被阻塞。

if(((*p)->signal & ~(_blockable & (*p)->blocked)) &&  

(*p)->state == task_interruptible)  

(*p)->state = task_running;    //置為就緒(可執行)狀態。

}  /* this is the scheduler proper: */

/* 這裡是排程程式的主要部分 */

while

(1)  

// 如果比較得出有counter 值大於0 的結果,則退出124 行開始的迴圈,執行任務切換(141 行)。

if(c)  

break

;  // 否則就根據每個任務的優先權值,更新每乙個任務的counter 值,然後回到125 行重新比較。

// counter 值的計算方式為counter = counter /2 + priority。[右邊counter=0??]

for(p = &last_task; p > &first_task; --p)  

if(*p)  

(*p)->counter = ((*p)->counter >> 1) + (*p)->priority;  

}  switch_to (next);     // 切換到任務號為next 的任務,並執行之。

}    

該段**有很多精巧之處,如果讓我自己來實現同樣的功能,**可能會很繁瑣。

精巧之處:

1、i起初賦值64,迴圈的時候先進行變數的--,然後再判斷,這樣正好執行63次,task0沒有必要迴圈判斷。

2、c起初賦值為-1,next賦值0,這樣可以解決當迴圈63次後,task[1]--task[63]沒有相應的任務在執行,這時,執行下一句break後,跳

出死迴圈,執行swtich_to(next)語句,正好切換到task[0],task0這時繼續迴圈執行pause()語句,呼叫排程函式。所以說task0是個閒置的

任務,只有task陣列沒有其他任務的時候才執行task0,讓task0繼續執行排程函式。重新排程程序執行。

Linux 核心 任務0的排程切換

main.c中在move to user mode 之後,切換到使用者模式下執行,task0然後執行fork 建立程序task1來執行init 函式。init 函式如下 void init void 下面是父程序執行的語句。wait 是等待子程序停止或終止,其返回值應是子程序的程序號 pid 這三句...

linux核心 5 核心程序排程與程序切換

一 程序排程 程序被建立到了鍊錶中,如何再進行進一步的呼叫和排程?程序排程 void schedule void 程序排程函式 switch to next 程序切換函式 一 void schedule void 程序排程函式 1 看一下 呼叫了schedule函式,在system call中尋找也...

Linux任務排程

任務排程 是指系統在某個時間執行的特定的命令或程度。任務排程分類 i.系統工作 有些重要的工作必須周而復始地執行。如病毒掃瞄等。ii.個別使用者工作 個別使用者可能希望執行某些程式。設定任務排程檔案 etc crontab 設定個人任務排程 crontab e 希望,每分去執行可以在crontab ...