我們都知道,使用者程式可以通過庫函式來通知核心執行系統呼叫,由於是在核心空間中執行,所以,每乙個步驟都需要非常小心,因為錯誤的操作隨時可以導致系統崩潰。
系統呼叫必須仔細檢查它們所有的引數是否合法有效。舉例來說,與檔案io相關的系統呼叫必須檢查檔案描述符是否有效。與程序相關的函式必須檢查提供的pid是否有效。必須檢查每個引數,保證它們不但合法有效,而且正確。程序不應該讓核心去訪問那些無權訪問的資源。
最重要的一種檢查就是檢查使用者提供的指標是否有效。試想,如果乙個程序可以給核心傳遞指標而又無需檢查,那麼它就可以給出乙個它根本沒有訪問許可權的指標,哄騙核心去為它拷貝不允許它訪問的資料。在接收乙個使用者空間的指標之前,核心必須保證:
1.指標指向的記憶體區域屬於使用者空間。程序決不能哄騙核心去讀核心空間的資料
2.指標指向的記憶體區域在程序的位址空間裡。程序決不能哄騙核心去讀其他程序的資料
3.如果是讀,該記憶體應該被標記為可讀;如果是寫,該記憶體應該被標記為可寫;如果是可執行,該記憶體被標記為可執行。程序決不能繞過記憶體訪問的限制
核心提供了兩個方法來完成必須的檢查和核心空間與使用者空間之間的資料的來回拷貝。注意,核心無論何時都不能輕率的接受來自使用者空間的指標!這兩個方法中必須經常有乙個被使用。
為了向使用者空間寫入資料,核心提供了 copy_to_user(),它需要三個引數。第乙個引數是程序空間的目的記憶體位址,第二個是核心空間的源位址,第三個引數時需要拷貝的資料長度(位元組數)。
為了從使用者空間中讀取資料,核心提供了 copy_from_user(),它和copy_to_user()相似。該函式把第二個引數指定的位置上的資料拷貝到第乙個引數指定的位置上,拷貝的資料長度由第三個引數指定。
如果執行成功,返回0;如果執行失敗,系統呼叫返回標準 -efault 。
下面貼出《linux核心設計與實現》中提供的乙個演示示例,這是乙個說明使用方法的示例,沒有價值。
[cpp]view plain
copy
print?
syscall_define3(silly_copy,
unsigned long
*, src,
unsigned long
*, dst,
unsigned long
len)
它所實現的功能是利用核心空間作為中轉,把使用者空間中的源位址資料拷貝到使用者空間中的目的位址處,如下圖所示:
linux中的系統呼叫
linux 0.11 中的close api解析 通常情況下,呼叫系統呼叫和呼叫普通自定義函式在 上並沒有什麼區別,但呼叫後發生的事情有很大不同。呼叫自定義函式是通過call指令直接跳轉到該函式的位址,繼續執行。呼叫系統呼叫是呼叫系統庫中為該系統呼叫編寫的乙個介面函式,即api。而api要做的就是去...
Linux中的系統呼叫
當使用者態的程序呼叫乙個系統呼叫時,cpu切換到核心態並開始執行乙個核心函式。核心實現了許多不同的系統呼叫,程序必須傳遞乙個名為系統呼叫號 system call number 的引數來識別所需的系統呼叫,eax暫存器就用作此目的。所有的系統呼叫均返回乙個整數值。系統處理程式與其他異常處理程式的結構...
Linux中的wait系統呼叫
系統中的殭屍程序都要由wait系統呼叫來 下面就通過實戰看一看wait的具體用法 wait的函式原型是 include 提供型別pid t的定義 include pid t wait int status 程序一旦呼叫了wait,就立即阻塞自己,由wait自動分析是否當前程序的某個子程序已經退出,如...