Linux內核分析 讀書筆記 (第五章)

第五章 系統調用

5.1 與內核通訊

1.調用在用戶空間進程和硬件設備之間添加了一箇中間層。該層主要做用有三個:linux

  • 爲用戶空間提供了硬件的抽象接口。
  • 系統調用保證了系統的穩定和安全。
  • 實現多任務和虛擬內存,保證良好的穩定性和安全性。

2.系統調用是用戶空間訪問內核的惟一手段;除異常和陷入外,是內核惟一合法的入口。編程

 

5.2 API、POSIX和C庫

1.狀況下,應用程序經過在用戶空間實現的應用編程接口(API)而不是直接經過系統調用來編程。api

2.C庫提供了POSIX的絕大部分API。安全

 

5.3 系統調用

1.要訪問系統調用(syscall),一般經過C庫中定義的函數調用來進行。函數

2.如何定義系統調用,注意:性能

  • asmlinkage爲限定詞,是一個編譯指令,通知編譯器僅從棧中提取該函數的參數。
  • 函數返回long。
  • 系統調用get_pid()在內核中被定義爲sys_getpid()。

5.3.1系統調用號

1.在Linux系統中,每一個系統調用被賦予一個系統調用號,這樣經過這個第一無二的號就能夠關聯繫統調用。當用戶空間的進程執行一個系統調用時,系統調用號用來指明執行哪一個系統調用;進程不會說起系統調用的名稱。spa

2.系統調用號一旦分配就不會再有任何變動,不然編譯好的應用程序就會崩潰。若是一個系統調用被刪除,所佔用的系統調用號也不準被回收利用。sys _ ni _ syscall()專門針對無效的系統調用而設立的,只返回-ENOSYS。設計

3.內核記錄了系統調用表中的全部已註冊的系統調用的列表,存儲在sys_call_table中。在x86-64中,他被定義於3arch/i386/kernel/syscall_64.c文件中,爲每個有效的系統調用指定惟一的系統調用號。指針

5.3.2系統調用的的性能

1.很短的上下文切換時間code

2.系統調用處理程序和每一個系統調用自己都很簡潔。

 

5.4 系統調用處理程序

5.4.1指定恰當的系統調用

1.在X86中,系統調用號經過eax寄存器傳遞給內核,system _ call()函數經過將給定的系統調用與NR _syscalls做比較來檢查其有效性,若是大於或等於NR _syscalls就返回-ENOSYS,不然就執行相應的系統調用:

call *sys_call_table(,%eax,8)//基址+偏移量*8

5.5系統調用的實現

5.5.1 實現系統調用

  • 他要作些什麼
  • 新系統調用的參數、返回值和錯誤碼又該是什麼?
  • 系統調用設計的越通用越好
  • 時刻注意可移植性和健壯性

5.5.2參數驗證

1.系統調用必須仔細檢查全部的參數是否合法有效,並且必須是正確的。

2.最重要的一種檢查是檢查用戶提供的指針是否有效,在接收一個用戶空間的指針以前,內核必須保證:

  • 指針所指向的內存區域屬於用戶空間。
  • 指針所指向的內存區域在進程的地址空間以內。
  • 若是是讀,該內存應被標記爲可讀,若是是寫,該內存應被標記爲可寫,若是是可執行,該內存應被標記爲可執行。進程決不能繞過內存訪問限制。

3.內核提供了兩個方法來完成必須的檢查內核空間與用戶空間數據的來回拷貝。

  • 爲了向用戶空間寫數據,內核提供了copy _ to _user(),它須要三個參數,第一個是進程空間中的目的內存地址,第二個是內核空間內的源地址,第三個是須要拷貝的數據長度(字節數)。

  • 爲了從用戶空間讀數據,內核提供了copy _ from _user(),該函數把第二個參數指定位置上的數據拷貝到第一個參數的指定位置,第三個是須要拷貝的數據長度(字節數)。

若是運行成功,則返回0,若是失敗,則返回沒能拷貝成功的字節數。

4.檢查針對是否有合法權限

調用capable()函數檢查用戶是否有權對指定資源進行操做,返回非0值則有權限,返回0無權限。

<linux/capability.h>中包含一份全部權能和其對應的權限列表。

5.6 系統調用上下文

1.內核在執行系統調用時處於進程上下文。在進程上下文中,內核能夠:

  • 休眠:說明系統調用可使用內核提供的絕大部分功能。
  • 能夠被搶佔:要求保證該系統調用是可重入的。

5.6.1 綁定一個系統調用的最後步驟

  1. 在系統調用表的最後加入一個表項。
  2. 對於所支持的各類體系結構,系統調用號都必須定義於<asm/unistd.h>中。
  3. 系統調用必須被編譯進內核映像(不能被編譯成模塊)。只要將其放進kernel/下的一個相關文件中便可,例如sys.c,它包含了各類各樣的系統調用。

5.6.2 從用戶空間訪問系統調用

1.一般,系統調用靠C庫支持。

2.Linux自己提供了一組宏,用於直接對系統調用進行訪問。他會設置好寄存器並調用陷入指令。

3.對於每一個宏來講,都有(2+2xn)個參數:

  • 第一個參數是系統調用的返回值類型
  • 第二個參數是系統調用的名稱
  • 再之後是按照系統調用參數的順序排列每一個參數的類型和名稱。
  • _ NR _open在<asm/unistd.h>中定義,是系統調用號。這個宏會被擴展成爲內嵌彙編的C函數。

5.6.3 爲何不經過系統調用的方式實現

好處:

  • 系統調用建立容易而且使用方便
  • linux系統調用的高性能

問題:

  • 你須要―個系統調用號,而這須要一個內核在處於開發版本的時候由官方分配給你
  • 系統調用被加入穩定內核後就被固化了,它的接口不容許作改動
  • 須要將系統調用分別註冊到每一個須要支持的體系結構中去
  • 在腳本中不容易調用系統調用,也不能從文件系統直接訪問系統調用
  • 因爲你須要系統調用號,所以在主內核樹以外是很難維護和使用系統調用的

替代方法:

實現一個設備節點,並對此實現read()和write()。使用特定的信息進行檢索。

  • 像信號量這樣的某些接口,能夠用文件描述符來表示,所以也就能夠按上述方式對其進行操做
  • 把增長的信息做爲一個文件放在sysfs的合適位置
相關文章
相關標籤/搜索