1. 程式人生 > >Linux系統程式設計 ---系統呼叫

Linux系統程式設計 ---系統呼叫

系統呼叫

計算機系統的各種硬體資源是有限的,在現代多工作業系統上同時執行的多個程序都需要訪問這些資源,為了更好的管理這些資源程序是不允許直接操作的,所有對這些資源的訪問都必須有作業系統控制。也就是說作業系統是使用這些資源的唯一入口,而這個入口就是作業系統提供的系統呼叫 (System Call)。 在Linux中系統呼叫是使用者空間訪問核心的唯一手段,除異常和陷入外,他們是核心唯一的合法入口。
這些系統呼叫按功能大致可分為如下幾類:
裝置管理:完成裝置的請求或釋放,以及裝置啟動等功能。
檔案管理:完成檔案的讀、寫、建立及刪除等功能。
程序控制: 完成程序的建立、撤銷、阻塞及喚醒等功能。
程序通訊: 完成程序之間的訊息傳遞或訊號傳遞等功能。
記憶體管理: 完成記憶體的分配、回收以及獲取作業佔用記憶體區大小及始址等功能。

系統呼叫說的也是作業系統提供給使用者程式呼叫的一組 “特殊”介面。使用者程式可以通過這組“特殊”介面來獲得作業系統核心提供的服務,比如使用者可以通過檔案系統相關的呼叫請求系統開啟檔案、關閉檔案或讀寫檔案,可以通過時鐘相關的系統呼叫獲得系統時間或設定定時器等。

從邏輯上來說,系統呼叫可被看成是一個核心與使用者空間程式互動的介面——它好比一箇中間人,把使用者程序的請求傳達給核心,待核心把請求處理完畢後再將處理結果送回給使用者空間。
這裡我們舉個例子來理解: 如果說你是一個悶騷且害羞的程式設計師, 那shell就像媒婆,作業系統核心就是你們村頭漂亮的且有讓你心動的MM小紅。你看上了小紅,但是又不好意思直接表白,那就讓你你家人找媒婆幫你提親,所有的事情你都直接跟媒婆溝通,由媒婆轉達你的意思給小紅,而我們找到媒婆姓王, 所以我們叫它王婆,它對應我們常使用的bash。

在這裡插入圖片描述
系統服務之所以需要通過系統呼叫來提供給使用者空間的根本原因是為了對系統進行“保護”, 因為我們知道Linux的執行空間分為核心空間與使用者空間,它們各自執行在不同的級別中,邏輯上相互隔離。所以使用者程序在通常情況下不允許訪問核心資料,也無法使用核心函式,它們只能在使用者空間操作使用者資料,呼叫使用者空間函式。比如我們熟悉的“hello world”程式(執行時)就是標準的使用者空間程序,它使用的列印函式printf就屬於使用者空間函式,列印的字元“hello word”字串也屬於使用者空間資料。

但是很多情況下,使用者程序需要獲得系統服務(呼叫系統程式),這時就必須利用系統提供給使用者的“特殊介面”——系統呼叫了,它的特殊性主要在於規定了使用者程序進入核心的具體位置;換句話說,使用者訪問核心的路徑是事先規定好的,只能從規定位置進入核心,而不准許肆意跳入核心。有了這樣的陷入核心的統一訪問路徑限制才能保證核心安全無誤。我們可以形象地描述這種機制

:作為一個遊客,你可以買票要求進入野生動物園,但你必須老老實實地坐在觀光車上,按照規定的路線觀光遊覽。當然,不準下車,因為那樣太危險,不是讓你丟掉小命,就是讓你嚇壞了野生動物。

系統呼叫的實現

系統呼叫是屬於作業系統核心的一部分的,必須以某種方式提供給程序讓它們去呼叫。CPU 可以在不同的特權級別下執行,而相應的作業系統也有不同的執行級別,使用者態和核心態。執行在核心態的程序可以毫無限制的訪問各種資源,而在使用者態下的使用者程序的各種操作都有著限制,比如不能隨意的訪問記憶體、不能開閉中斷以及切換執行的特權級別。顯然,屬於核心的系統呼叫一定是執行在核心態下。
關於如何切換到核心態呢?我上篇部落格詳細介紹過: Linux下如何從使用者態切換到核心態?

系統呼叫和庫函式的區別

Linux 下對檔案操作有兩種方式:系統呼叫(system call)和庫函式呼叫(Library functions)。

庫函式由兩類函式組成:

1)不需要呼叫系統呼叫

不需要切換到核心空間即可完成函式全部功能,並且將結果反饋給應用程式,如strcpy、bzero 等字串操作函式。

2)需要呼叫系統呼叫

需要切換到核心空間,這類函式通過封裝系統呼叫去實現相應功能,如 printf、fread等。
在這裡插入圖片描述

資料來源: https://blog.csdn.net/tennysonsky/article/details/45101303