作業系統

當前位置 /首頁/計算機/作業系統/列表

Linux系統下的程序切換的解析

Linux核心下程序切換

Linux系統下的程序切換的解析

Linux切換並沒有使用X86CPU的切換方法,Linux切換的實質就是cr3切換(記憶體空間切換,在switch_mm函式中)+ 暫存器切換(包括EIP,ESP等,均在switch_to函式中)。這裡我們講述下switch_to主流程

1、 在switch_mm函式中將new_task->pgd設定到cr3暫存器中,實現頁表切換,由於每個程序3-4G的頁表對映機制完全一樣(從核心頁表中直接複製過來的),故這裡雖然切換了pgd,但是並無影響,只是在任務回到使用者空 間中時,才會發生變化,因為每個任務在0-3G中的頁表對映都是各自獨立的;

2、 壓入esi edi ebp到cur_task堆疊中;

3、 將esp暫存器中的值儲存到cur__中,也就是將cur_task切換時的堆疊指標儲存起來;

4、 將new__中的值設定到esp暫存器中,這裡的new__中的值就是new_task上一次被換出時的堆疊指標,現在被恢復了,2和3結合實現了從cur_task到new_task的堆疊切換;

5、 將1f地址設定到cur__中,當下次cur_task恢復執行時,將會從1f處開始執行,下面闡述了這種原理;

6、 將new__壓入到new_task的堆疊中,這裡new__的值就是1f,因為從4中可知,new_task上一次被換出時,其也是和現在的cur_task類似,1f地址被設定到new__中;

7、 隨後CPU跳轉到__switch_to函式中開始執行,注意這裡使用的是jmp,不是call,call會pusheip,而jmp不會,由於__switch_to是函式,當CPU執行完該函式後,最後一條指令必然為iret,該指令會popeip,從5中可以知道,此時new_task堆疊中的映象為[......., esi,edi,ebp,eip(&1f)],故popeip將值eip(&1f)設定到eip暫存器中,這樣當iret執行完畢後,CPU將從eip處繼續執行,也就是從1f處繼續執行;

8、 此時已經在new_task的執行環境中了,pop ebp, pop edi, popesi,回到schedule函式中,當返回使用者空間中時,由於new_task使用者空間的eip,ss,esp等均被從new_task的堆疊中彈出到對應暫存器中,從而new_task得以順利執行。

Linux 前後臺程序切換

當你用shell啟動一個程式時,往往他是在前臺工作的。 例如經常用PUTTY連線到遠端伺服器執行指令碼的時候,如果本地網路中斷後,這個時候前臺程序就結束了,比較的懊惱,必須重新執行。因此有必要進行前後臺程序的切換。

例如直接在終端裡輸入firefox,那麼會開啟firefox,但當你關閉此終端或者ctrl+c強制終止時,firefox也隨機關閉了。

你可以在執行時後面加一個&,這樣就在後臺工作了。Shell支援作用控制,有以下命令:

(1). command &讓程序在後臺執行

(2). jobs –l 檢視後臺執行的.程序

(3). fg %n 讓後臺執行的程序n到前臺來

(4). bg %n 讓程序n到後臺去;

PS:"n"為jobs檢視到的程序編號。

1、執行命令&切換至後臺

在Linux終端執行命令的時候,在命令末尾加上&符號,就可以讓程式在後臺執行

程式碼如下:

root@Ubuntu$ ./tcpserv01&

2、切換正在執行的程式到後臺

如果程式正在前臺執行,可以使用Ctrl+z 選項把程式暫停,然後用 bg %[number]命令把這個程式放到後臺執行,這個步驟分為3步,如下:

2.1暫停程式執行CTRL+Z

ctrl + z跟系統任務有關的,ctrl + z可以將一個正在前臺執行的命令放到後臺,並且暫停。

程式碼如下:

[Oracle@linuxidc ~]$ sh

[1]+Stopped

2.2檢視暫停的程式

察看jobs使用jobs或ps命令可以察看正在執行的jobs。

程式碼如下:

[oracle@linuxidc ~]$ jobs -l

[1]+ 4524Stopped

jobs命令執行的結果,+表示是一個當前的作業,減號表是是當前作業之後的一個作業。

jobs -l選項可顯示所有任務的PID,jobs的狀態可以是running, stopped,Terminated

2.3切換程式至後臺

bg將一個在後臺暫停的命令,變成繼續執行如果後臺中有多個命令,可以用bg %jobnumber將選中的命令調出.

程式碼如下:

[oracle@linuxidc ~]$ bg %1

[oracle@linuxidc ~]$ jobs -l

[1]+ 4524Running

2.4切換程式至前臺

也可以用 fg %[number]指令把一個程式掉到前臺執行

程式碼如下:

[oracle@linuxidc ~]$ fg %1

./tcpserv01

2.5終止後臺程式

也可以直接終止後臺執行的程式,使用 kill 命令

程式碼如下:

[oracle@linuxidc ~]$ kill %1

但是如果任務被終止了(kill),shell 從當前的shell環境已知的列表中刪除任務的程序標識;也就是說,jobs命令顯示的是當前shell環境中所起的後臺正在執行或者被掛起的任務資訊。