os
為使用者態執行的程序與硬體裝置進行互動提供了一組介面,有三個優點:從低階程式設計中解放、提高安全性、可移植性。
api與系統呼叫:前者是函式定義,後者通過陷阱明確向核心發請求。每個系統呼叫一般對應於乙個
c庫中的封裝例程,而這個封裝例程,即為應用程式
api。乙個單獨的
api函式可能呼叫
n個系統呼叫,也可能沒對應任何系統呼叫,也有可能幾個
api對應同乙個系統呼叫如
malloc
與free
都是brk
系統呼叫。
posix
標準針對
api而非系統呼叫,程式設計者來看無差別,核心設計者觀點看系統呼叫屬核心,使用者態庫函式不屬於核心。使用者態程序呼叫一系統呼叫時,
cpu切換到核心態並開始執行乙個核心函式,即「系統呼叫處理程式」。核心中系統呼叫按號碼識別,使用者態的系統呼叫在封裝例程中會自動生成系統呼叫號,存在
eax暫存器中,如
fork()
存編號2
。系統呼叫返回也經過封裝例程處理後返回給使用者態程序。呼叫系統呼叫時,在封裝例程中,將引數處理完後,由彙編指令如
int 0x80
進入核心的系統呼叫處理程式,它將暫存器入核心棧,呼叫系統呼叫服務例程,最後從處理程式返回。
封裝例程中進入系統呼叫有兩種:一是
int 0x80
,這是老
linux
核心進入核心態的唯一方式。核心初始化時,將中斷描述符表項相關字段初始化為核心**段、將系統呼叫處理程式指標初始化為
eip、設為陷阱、特權等級為3。此
int指令跳轉到之前所說的
system_call()
,該函式將系統呼叫號和異常處理程式所用的
cpu暫存器入棧(不包括硬體自動儲存的
eflags、cs
、eip、ss
、esp
)、檢查有無除錯程式跟蹤、檢查系統呼叫號。系統呼叫號與系統呼叫服務例程的對應關係存在系統呼叫分派表中。如果沒問題,就呼叫分派表中對應的服務例程。使用者態給的其它引數怎麼辦?不能靠棧傳,因為這裡涉及使用者棧與核心棧,所以只能用暫存器間接傳。事實上在封裝例程中引數已入暫存器。系統呼叫處理程式中將暫存器入棧,造成服務例程可直接從核心棧中取引數。用
regs
傳引數的限制是引數不可多於
6個,否則暫存器數量不夠。此外引數長度也受限制。引數傳來後,得檢查其中的位址是否屬於此程序的位址空間,但這花時間多且此錯誤發生可能性較小。後來,僅僅判斷位址是否越入核心位址空間、之前的錯誤放到後面去捕捉,單獨將是否侵入核心位址空間的檢查提前是因為使用者態程序可能誤將核心位址空間的位址作為引數傳,還能在不引起缺頁異常的情況對記憶體中現有任何頁讀寫。在系統呼叫服務例程中,需頻繁訪問程序位址空間資料,若之前粗略檢查的位址號雖在
0xc0000000
前但不屬於程序位址空間會發生什麼?先回顧缺頁異常在核心可能發生的條件:
1.訪問使用者態位址空間的頁,但頁框不存在或試圖寫唯讀頁。這時用請求調頁分配頁框即可;
2.核心定址到屬於其他程序位址空間的頁,但表項未初始化,此時只要在頁表中建立相應的表項(發生在非連續記憶體訪問);
3.核心函式程式設計錯誤或硬體出問題;
4.讀乙個由系統呼叫引數傳入的位址,但它不屬於程序的位址空間。後兩種可如此解決:考慮訪問程序位址空間的指令有限,因此可將它們列乙個表,叫異常表,每個表由指令的線性位址和發生這種情況時要呼叫的修正措施的彙編**位址,後者稱作修正**。這樣,當缺頁異常的3、
4兩種情況發生時,查異常表,若有,則說明呼叫引數非法,若無,則說明核心出
bug了。異常表在建立核心程式映像時由
c編譯器生成,存放在核心**段的
__ex_table
節中。此外,動態裝載的核心模組也有自己的區域性異常表,也在建立模組映像時
c編譯器生成。修正通常是強**務例程返回出錯碼給使用者態程序。
另一種新的進入系統呼叫指令是
sysenter
,它因為有特殊暫存器的幫助,所以速度快,總體的過程差不多。
核心執行緒也可呼叫系統呼叫,但因為它不能用庫函式,
linux用7
個巨集來完成對應工作。
read系統呼叫,mmap系統呼叫
read系統呼叫,mmap系統呼叫 2012 07 23 09 54 28 分類 linux 標籤 linux 檔案系統 虛擬記憶體 儲存系統 字型大小 訂閱 一般情況下,操作檔案既可以使用標準i o,也可直接使用系統呼叫。兩者有何區別呢?在輸入輸出中,直接使用底層的系統呼叫效率是非常低的,為什麼?...
庫呼叫,系統呼叫
通過這個問題,可以判斷候選人是否具有豐富的程式設計經驗以及是否具有找出這類問題答案的敏銳感覺。簡明的回答是 函式庫呼叫是語言或應用程式的一部分,而系統呼叫是作業系統 的一部分。你要確保弄懂 trap 自陷 這個關鍵字的含義。系統呼叫是在作業系統核心發現乙個 trap 或中斷後進行的。函式庫呼叫 vs...
系統呼叫 函式呼叫
linux下對檔案操作有兩種方式 提供了庫函式,如open close read write ioctl 等,需包含標頭檔案unistd.h。以write 函式為例 其函式原型為size t write int fd,const void buf,size t nbytes 其操作物件為檔案控制代碼...