void testfork()
printf(「testfork ok\n」);
}
如果說前面兩種是靜態觀察的角度看的話,我們還可以從動態的角度來看這段**,即它被轉換成cpu執行的指令後載入執行的過程,這時這段程式就是乙個動態執行的指令序列。而究竟載入了哪些**,如何載入就是和作業系統密切相關了。
熟悉unix/linux系統的人都知道,fork的工作實際上是以系統呼叫的方式完成相應功能的,具體的工作是由sys_fork負責實施。其實無論是不是unix或者linux,對於任何作業系統來說,建立乙個新的程序都是屬於核心功能,因為它要做很多底層細緻地工作,消耗系統的物理資源,比如分配物理記憶體,從父程序拷貝相關資訊,拷貝設定頁目錄頁表等等,這些顯然不能隨便讓哪個程式就能去做,於是就自然引出特權級別的概念,顯然,最關鍵性的權力必須由高特權級的程式來執行,這樣才可以做到集中管理,減少有限資源的訪問和使用衝突。
特權級顯然是非常有效的管理和控制程式執行的手段,因此在硬體上對特權級做了很多支援,就intel x86架構的cpu來說一共有0~3四個特權級,0級最高,3級最低,硬體上在執行每條指令時都會對指令所具有的特權級做相應的檢查,相關的概念有 cpl、dpl和rpl。硬體已經提供了一套特權級使用的相關機制,軟體自然就是好好利用的問題,這屬於作業系統要做的事情,對於 unix/linux來說,只使用了0級特權級和3級特權級。也就是說在unix/linux系統中,一條工作在級特權級的指令具有了cpu能提供的最高權力,而一條工作在3級特權級的指令具有cpu提供的最低或者說最基本權力。
為什麼使用者態到核心態切換消耗大?
核心態和使用者態有自己的記憶體對映,即自己的位址空間。
使用者空間的應用程式,通過系統呼叫,進入核心空間。由核心代表該程序執行於核心空間,這就涉及到上下文的切換,使用者空間和核心空間具有不同的位址對映,通用或專用的暫存器組,而使用者空間的程序要傳遞很多變數、引數給核心,核心也要儲存使用者程序的一些暫存器、變數等,以便系統呼叫結束後回到使用者空間繼續執行。
所謂的「程序上下文」,就是乙個程序在執行的時候,cpu的所有暫存器中的值、程序的狀態以及堆疊上的內容,當核心需要切換到另乙個程序時,它需要儲存當前程序的所有狀態,即儲存當前程序的程序上下文,以便再次執行該程序時,能夠恢復切換時的狀態,繼續執行。
現在我們從特權級的排程來理解使用者態和核心態就比較好理解了,當程式執行在3級特權級上時,就可以稱之為執行在使用者態,因為這是最低特權級,是普通的使用者程序執行的特權級,大部分使用者直接面對的程式都是執行在使用者態;反之,當程式執行在級特權級上時,就可以稱之為執行在核心態。
雖然使用者態下和核心態下工作的程式有很多差別,但最重要的差別就在於特權級的不同,即權力的不同。執行在使用者態下的程式不能直接訪問作業系統核心資料結構和程式,比如上面例子中的testfork()就不能直接呼叫 sys_fork(),因為前者是工作在使用者態,屬於使用者態程式,而sys_fork()是工作在核心態,屬於核心態程式。
當我們在系統中執行乙個程式時,大部分時間是執行在使用者態下的,在其需要作業系統幫助完成某些它沒有權力和能力完成的工作時就會切換到核心態,比如testfork()最初執行在使用者態程序下,當它呼叫fork()最終觸發 sys_fork()的執行時,就切換到了核心態。
1.使用者態切換到核心態的3種方式
a. 系統呼叫
這是使用者態程序主動要求切換到核心態的一種方式,使用者態程序通過系統呼叫申請使用作業系統提供的服務程式完成工作,比如前例中fork()實際上就是執行了乙個建立新程序的系統呼叫。而系統呼叫的機制其核心還是使用了作業系統為使用者特別開放的乙個中斷來實現,例如linux的int 80h中斷。
b. 異常
當cpu在執行執行在使用者態下的程式時,發生了某些事先不可知的異常,這時會觸發由當前執行程序切換到處理此異常的核心相關程式中,也就轉到了核心態,比如缺頁異常。
c. 外圍裝置的中斷
當外圍裝置完成使用者請求的操作後,會向cpu發出相應的中斷訊號,這時cpu會暫停執行下一條即將要執行的指令轉而去執行與中斷訊號對應的處理程式,如果先前執行的指令是使用者態下的程式,那麼這個轉換的過程自然也就發生了由使用者態到核心態的切換。比如硬碟讀寫操作完成,系統會切換到硬碟讀寫的中斷處理程式中執行後續操作等。
這3種方式是系統在執行時由使用者態轉到核心態的最主要方式,其中系統呼叫可以認為是使用者程序主動發起的,異常和外圍裝置中斷則是被動的。
2.具體的切換操作
從觸發方式上看,可以認為存在前述3種不同的型別,但是從最終實際完成由使用者態到核心態的切換操作上來說,涉及的關鍵步驟是完全一致的,沒有任何區別,都相當於執行了乙個中斷響應的過程,因為系統呼叫實際上最終是中斷機制實現的,而異常和中斷的處理機制基本上也是一致的,關於它們的具體區別這裡不再贅述。關於中斷處理機制的細節和步驟這裡也不做過多分析,涉及到由使用者態切換到核心態的步驟主要包括:
[1] 從當前程序的描述符中提取其核心棧的ss0及esp0資訊。
[2] 使用ss0和esp0指向的核心棧將當前程序的cs,eip,eflags,ss,esp資訊儲存起來,這個過程也完成了由使用者棧到核心棧的切換過程,同時儲存了被暫停執行的程式的下一條指令。
[3] 將先前由中斷向量檢索得到的中斷處理程式的cs,eip資訊裝入相應的暫存器,開始執行中斷處理程式,這時就轉到了核心態的程式執行了。
關於Linux的預備知識
最高許可權賬戶為 root,可以操作一切!在linux領域內大多用在伺服器上,很少遇到關機的操作。畢竟伺服器上跑乙個服務是永無止境的,除非特殊情況下,不得已才會關機。關機指令為 shutdown sync 將資料由記憶體同步到硬碟中。shutdown 關機指令,你可以man shutdown 來看一...
Linux 01day 預備知識
版本 ubuntu16.04 切換到超級使用者 sudo su 退出超級使用者 exit 暫時使用超級使用者許可權 sudo 命令 shell和bash統稱為 命令解析器 游標移動的位置 向上 ctrl p previous 向下 ctrl n next 向左 ctrl b backward 向右 ...
三 系統呼叫
1.概念 作業系統對上提供服務的介面 2.程式呼叫與系統呼叫的不同之處?3.開銷?系統呼叫 介面呼叫核心態中的系統呼叫功能實現,並返回系統呼叫的狀態和結果 使用者不需要知道系統呼叫的實現 系統呼叫 函式呼叫 為了呼叫乙個函式需要把引數壓到堆疊裡,轉到相應的函式去執行,執行時從堆疊裡獲取我的引數資訊執...