深入理解linux核心讀書筆記(第九章)

2021-07-03 05:48:43 字數 3685 閱讀 3263

1. 核心信賴自己,但是對於使用者態的記憶體請求,核心會做必要的位址檢查,然後先給程序分配位址空間(線性位址),真正的物理記憶體分配推遲到必要的時候才進行。

2. 核心使用mm_struct 來描述使用者的位址空間資訊,所有的mm_struct 是用雙向鍊錶連線起來的,相鄰的mm_struct 在mmlist域中表示,鍊錶中的第乙個元素是init_mm中mmlist指向的程序0的mm_struct。

3. mm_users 域用來儲存共享記憶體描述符的執行緒數, mm_count域是mm_struct 的引用計數,每次mm_count減小時,核心都檢查其是否等於0,如果是的話,就釋放該描述符。

4. mm_alloc用來分配新的程序空間描述符,通過slab cache來分配,並且將mm_users和mm_count 都初始化為1.

5. mmput將mm_users減小1,如果 等於0, 就釋放ldt,記憶體區域描述符和相關聯的頁表,並且呼叫mmdrop,mmdrop將mm_count 減1,如果等於0, 就釋放程序空間描述符。

6. 核心執行緒和普通程序不同,它不使用程序空間。對於task_size以上的記憶體,所有的程序都是相同的,所以核心執行緒使用在它之前的程序頁表。

7. 對於普通程序,mm 和active_mm應該是相同的,但是對於核心執行緒,mm 為null, active_mm指向之前程序的active_mm所指向的程序空間描述符。

8. 當核心更新task_size之上的記憶體對映時(vmalloc,vfree),核心只更新主頁表,其他程序的頁表資訊會通過page_fault處理函式來進行更新。

9. vm_area_struct 用來表示乙個記憶體區域,範圍是[vm_start, vm_end),當新增或移除乙個記憶體區域時,核心嘗試將許可權相同的,位址連續的區域進行合併。起始位址和大小均為頁對齊。

10. 乙個程序的所有記憶體區域通過乙個簡單鍊錶按照位址的大小連線起來,vm_area_struct 中的vm_next域指向下乙個記憶體區域,mm_struct 的mmap 指向該程序的第乙個記憶體區域,map_count儲存程序擁有的記憶體區域個數。

11. linux 2.6中用了紅黑樹來快速查詢某個記憶體區域,由mm_rb指向根節點。

12. vm_area_struct 中的vm_flags用來表示該記憶體區域的一些屬性,包括訪問許可權,共享許可權以及增長方式等資訊。

13 初始的頁表flags儲存在vm_area_struct 中的vm_page_port欄位中。

14. find_vma接收mm_struct和addr兩個引數,用來找到第乙個vm_end大於addr的vm_area_struct的位址,沒有找到的話,返回null。

15. mm_struct中的mmap_cache指向該程序上次訪問的vm_area_struct , find_vma會首先檢查該記憶體區域是否包含addr,如果是,立即返回, 否則的話,通過紅黑樹來進行查詢。

16. find_vma_intersection用來查詢覆蓋一段位址的記憶體區域。

18. insert_vm_struct將乙個vm_area_struct 插入到鍊錶和紅黑樹中,如果是匿名對映的話,還要與anon_vma進行關聯。

19. mmap函式為程序建立並且初始化乙個新的記憶體區域,但是有可能和之前的區域合併。

20. get_user_pages 函式會遍歷乙個指定的使用者記憶體區間,對於每乙個頁,呼叫follow_page來檢查是否有相應的物理頁面,如果沒有的話,會呼叫handle_mm_fault來分配物理頁面並且建立頁表。

21. do_page_fault函式是x86平台的頁故障異常處理函式,它接收pt_regs 指標和error_code。

22 error_code由3個bit組成:

(1)bit 0如果置位,表示許可權非法,否則,表示頁面不存在。

(2)bit 1如果置位,表示是寫異常,否則,為讀或執行異常。

(3)bit 2如果置位,表示異常發生在使用者態,否則,發生在核心態。

23. 當頁故障發生時,發生故障的頁的線性位址放入了cr2暫存器。

24. in_atomic函式檢查核心是否在關鍵區內,如果是以下情況,則返回真:

(1) 核心正在執行中斷處理函式或者延遲函式。

(2)核心正在執行關鍵區的**,並且已經關閉核心搶占。

25.  滿足in_atomic 或者是核心執行緒時, 缺頁會導致核心錯誤,產生oops。

26. 為了讀取使用者程序的記憶體資訊,需要獲取mm->mmap_sem,為了防止造成死鎖,使用down_read_trylock,如果無法獲取鎖,該訊號量可能是被別的系統呼叫占用了,這種情況的話,就等待訊號量被釋放,否則,就是核心bug,產生oops。

27.  對於異常的位址不在程序的vma中,還有一種額外的情況是由於push操作導致的棧增長,vm_end不變,vm_start 減小, 異常的位址應該只比sp小一點,否則的話,也是bug。確認是棧擴充套件的話,呼叫expand_stack, 改變vm_start的值,賦值為 address & page_mask。

28.  如果是使用者態的程序不包含異常位址,進入bad_area函式,向使用者程序傳送sigsegv訊號。

29.  在訪問許可權沒有問題的情況下,接下來呼叫handle_mm_fault函式來分配物理頁面。返回vm_fault_minor表示頁故障不會阻塞當前程序,vm_fault_major表示會導致當前程序阻塞。

30. handle_mm_fault 會先檢查相應的頁目錄,頁表是否存在,不存在的話,就分配。handle_pte_fault用於處理最後的頁表項,如果頁表項是空,就是demand paging;如果是唯讀,就是copy on write (cow)。

31.  (1) 如果pte_none返回1,頁表項全部為0, 表示該頁從來沒被訪問或者為乙個線性檔案對映,如果vm_ops不空,可能是檔案對映,否則為匿名對映。

(2) 如果頁屬於乙個非線性檔案對映,p清零,d位置1。

(3)    如果頁被訪問過,但是目前被置換到磁碟,p, d位都清零。

32.  do_anoymous_page 在處理讀請求時,將pte設定為系統預先分配的0頁記憶體,許可權為唯讀, 後續的寫操作會導致cow; 如果為寫請求,則需要分配物理頁。

33. cow技術:page結構體的_count域表示共享該頁的程序數,當程序釋放page或者發生cow時,_count減1, 當_count為-1時,真正釋放該頁。

34. 當handle_pte_fault發現p為置1, 並且頁表項為唯讀,請求為寫,此時呼叫do_wp_page,該函式來讀取_count等資訊來決定是否執行cow。

35. 如果發生在核心空間,並且位址大於task_size, 會進入vmalloc_fault, 將主核心頁表複製到使用者程序的頁表中。

36. linux執行緒是通過clone函式,傳入clone_vm引數來建立的,執行緒之間共享位址空間。

37. copy_mm用來建立新程序的位址空間,如果clone_vm設定了,就直接使用父程序的mm, 否則,需要呼叫dup_mm來複製父程序的mm,並且修改一些字段。dup_mm 會呼叫dup_mmap來複製記憶體區域和頁表。

38. 程序退出時,呼叫exit_mm來釋放程序空間, 首先會將mm_count加1, mmput最後會釋放ldt, vma和頁表。mm本身不會被銷毀,而是在schedule中的finish_task_switch中的mmdrop來進行銷毀。

39. mm->brk用來表示程序的堆頂,brk是乙個系統呼叫,c庫中的堆操作都是通過brk和mmap來實現的。如果是縮減堆,則會呼叫do_munmap; 擴充套件堆的話,會呼叫do_brk, 該函式相當於乙個只處理匿名記憶體區域的do_mmap,而不考慮檔案對映。

《深入理解Linux核心》 讀書筆記

使用者和組 程序核心體系結構 硬鏈結和軟連線 檔案型別 檔案描述符與索引節點 訪問許可權和檔案模式 檔案操作 程序可重入核心 程序位址空間 同步和臨界區 訊號和程序間通訊 核心收到訊號後,可以 程序間通訊 ipc 程序管理 記憶體管理 邏輯位址,經過分段單元,轉換為線性位址,線性位址,經過分頁單元,...

《深入理解Python》讀書筆記

1 type函式返回任意物件的資料型別。type可以接收任何東西作為引數 整型 字串 列表 字典 元組 函式 類 模組 甚至型別物件,並返回它的資料型別。可以使用types模組中的常量來進行物件型別的比較。import mymodule import types type mymodule type...

深入理解Linux核心 筆記

第一章 緒論 1.unix檔案可以是下列型別之一 a.正規檔案 regular file b.目錄 directroy c.符號鏈 symbolic link d.塊裝置檔案 block oriented device file e.字元裝置檔案 charactor oriented device ...