由作業系統提供的功能,通常應用程式本身是無法實現的。例如對檔案進行操作,應用程式必需通過系統呼叫才能做到,因為只有作業系統才具有直接管理外圍裝置的許可權。又如程序或執行緒間的同步互斥操作,也必需經由作業系統對核心變數進行維護才能完成。
從下到上看乙個完整的計算機系統:物理硬體->os核心->os服務->應用程式。這裡的os核心起到了「承上啟下」的關鍵作用,向下管理物理硬體,向上為作業系統服務和應用程式提供介面,這裡的介面就是系統呼叫了。
應用程式的程序通常在user模式下執行,當它呼叫乙個系統呼叫時,程序進入kernel模式,執行的是kernel內部的**,從而具有執行特權指令的許可權,完成特定的功能。換句話說,系統呼叫是應用程式主動進入作業系統核心的入口。
顧名思義是把函式放到庫里,是把一些常用到的函式編完放到乙個檔案裡,供別人用。別人用的時候把所在的檔名用#include<>加到裡面就可以了,一般放到lib檔案裡。
庫函式主要由兩方面提供:一是作業系統提供的;另一類是由第三方提供的。
事實上,系統呼叫所提供給使用者的是直接而純碎的高階服務,如果想要更加人性化,具有更符合特定情況的功能,那麼就要我們使用者自己定義,因此衍生了庫函式,它把部分系統呼叫包裝起來。比如當我們要用c語言列印一句話的時候,如果沒有用到庫函式printf,那麼我們就需要自己實現就需要呼叫putc()和write()等這樣一些系統函式。顯得比較麻煩,所以系統呼叫是為了方便使用作業系統的介面,而庫函式則是為了人們程式設計的方便。
例如,在linux作業系統下,c語言的庫函式printf,實際上使用了write系統呼叫;而庫函式strcpy(字串拷貝)卻沒有使用任何系統呼叫。另外,乙個系統的系統呼叫介面通常是能夠完成所有必需功能的最小集合,可能存在多個庫函式對同乙個系統呼叫進行封裝。例如,在linux中,malloc、calloc和free三個庫函式底層都是呼叫brk系統呼叫完成的。
應用程式、庫函式和系統呼叫的關係如下圖所示:
庫函式的呼叫是語言或者應用程式的一部分,而系統呼叫則是作業系統的一部分。
系統呼叫是應用程式與核心互動的介面。人們在長期的程式設計中發現使用系統函式有個重大的缺點,那就是程式的移植性。例如linux提供的系統呼叫的函式和windows就不一樣。
庫函式呼叫則是面向應用開發的,相當於應用程式的api,採用這樣的方式有很多原因:
通常,處理器設有兩種模式:「使用者模式」與「核心模式」,通過乙個標籤位來鑑別當前正處於什麼模式。核心模式可以執行所有指令,包括特權指令(主要是一些硬體管理的指令,例如修改基址暫存器內容的指令) ,而使用者模式不能執行特權指令。這樣的設計主要為了安全問題,即由作業系統負責管理硬體,避免上層應用因錯誤設計而導致硬體問題。
既然只有作業系統能直接操作硬體,作業系統有必要提供介面來為應用程式提供使用硬體功能的入口,這些介面就被稱為系統呼叫。
當作業系統接收到系統呼叫請求後,會讓處理器進入核心模式,從而執行諸如i/o操作,修改基址暫存器內容等指令,而當處理完系統呼叫內容後,作業系統會讓處理器返回使用者模式,來執行使用者**。
對應cpu的核心模式和使用者模式,程序執行的狀態分為管態(核心態)和目態(使用者態)。具體請看文章:作業系統--使用者態和核心態
中斷(interrupt)通常是指在cpu內部或外部發生了某個待處理的事件,從而cpu必需改變當前指令的執行順序去處理這類事件。在介紹中斷和系統呼叫的關係之前,下面先把中斷做乙個分類。
中斷可以大體分為兩大類:
synchronous interrupts (異常)又分為以下若干類:
至此,我們發現了中斷與系統呼叫的關係:系統呼叫是一種特殊的中斷型別(軟中斷)。
在x86的機器中,用乙個8bit的數字(0~255)來區分各種中斷,這個數字被稱為中斷向量(vector)。其中乙個中斷向量,即128 (0x80),專門被用於執行系統呼叫。
在linux系統中,存有乙個系統表,叫做interrupt descriptortable,簡稱idt。idt表共有256項,存放了從中斷向量到相應處理例程(interrupt or exceptionhandler)的對映關係。當某個中斷發生時,cpu從idt表中查詢到相應的處理例程的位址來執行。
系統呼叫的處理例程在idt表中占有一項。這一項是在trap_init函式中被初始化的,如下:set_system_gate(syscall_vector,&system_call);
。如前所述,上面**中的syscall_vector的值是128。
當系統呼叫發生時,通過中斷機制,系統呼叫例程system_call被呼叫。它的執行過程大概分為4個步驟:
從暫存器中取出系統呼叫號和輸入引數,然後將這些暫存器的值壓入kernel棧中。
根據系統呼叫號查詢系統呼叫分派表(system call dispatch table),找到系統呼叫服務例程(乙個核心函式)。
呼叫查到的系統呼叫服務例程。
將系統呼叫服務例程的返回值出棧,重新儲存在暫存器中。
上面描述的系統呼叫例程system_call在kernel空間中執行。在執行前,系統呼叫號和輸入引數已經存入了暫存器,這個存入過程由user空間的**完成。實際上,如同第一節所講,每個真正的系統呼叫基本上都有乙個封裝它的庫函式,一般是在這個庫函式中完成系統呼叫號和輸入引數的儲存動作。當系統呼叫例程system_call執行完畢後,返回值通過暫存器再傳回user空間的庫函式。
kernel入口--system call
作業系統(六)系統呼叫
在前幾篇文章中曾經提到過系統呼叫程式介面,並提到系統呼叫使應用程式請求作業系統服務的唯一方式。下面再來更進一步地學習一下。目錄 1.6 系統呼叫 1.6.1 系統呼叫 1.6.2 系統呼叫的具體使用場景 1.6.3 系統呼叫的過程 系統呼叫 是作業系統提供給應用程式 程式設計師 程式設計人員 使用的...
作業系統(3)系統呼叫
作業系統作為使用者和計算機硬體之間的介面,需要向上提供一些簡單的服務。主要包括命令介面和程式介面。其中程式介面由一組系統呼叫組成。1 命令介面 允許使用者直接使用 聯機命令介面 使用者說一句,系統做一句。離線命令介面 使用者說一堆,系統做一堆。2 程式介面 允許使用者通過程式間接使用 由一組系統呼叫...
(作業系統課程專案)系統呼叫
一 實驗目的 學習linux核心的系統呼叫,理解 掌握linux系統呼叫的實現框架 使用者介面 引數傳遞 進入 返回過程。閱讀linux核心源 通過新增乙個簡單的系統呼叫實驗,進一步理解linux作業系統處理系統呼叫的統一流程。二 實驗內容1.2.系統呼叫的功能是將自己的名字和學號在終端或核心日誌裡...