(1)內核基礎層提供的服務

操作系統通常提供的服務是內存管理、進程管理、設備管理、文件系統

一. 內核中使用內存

內核提供了兩個層次的內存分配接口:從夥伴系統分配、從slab系統分配。
夥伴系統是最底層的內存管理機制,提供頁式的內存管理。
slab是夥伴系統之上的內存管理,提供基於對象的內存管理。

從夥伴系統分配內存調用的是alloc_pages,此時得到的是頁面地址,要獲得能使用的內存地址,需要調用page_address來獲得內存地址。(直接獲取內存地址可以使用__get_free_pages)。

alloc_pages申請的內存是以頁爲單位的,最少要一個頁。如果只是申請一小塊內存,一個頁就浪費了,而且內核中很多應用也希望一種對象化的內存管理,希望內存管理能自動地構造和析構對象,這就是slab內存管理。

要從slab申請內存,需要創建一個slab對象,使用kmem_cache_create創建slab對象。kmem_cache_create可以提供對象的名字和大小、構造函數和析構函數等,然後通過kmem_cache_alloc和kmem_cache_free來申請和釋放內存。

內核中常用的kmalloc其實也是slab提供的對象管理,只不多內核已經構建了一些固定大小的對象,用戶通過kmalloc申請時,就使用了這些對象。

內核中還有一個內存分配調用:vmalloc。vmalloc的作用是把物理地址不連續的內存頁面拼湊爲邏輯地址連續的內存區間。

二. 內核中的任務調度

內核中經常需要進行進程的調度,使用wait_event實現。內核中還實現了一系列函數:
wait_event_timerout:和wait_event的區別是有時間限制,如果條件滿足,進程恢復運行,或者時間到達,進程同樣恢復進行。
wait_event_interruptible:和wait_event類似,不同之處是進程處於可中斷的睡眠。而wait_event設置進程處於不可中斷的睡眠。
wait_event_interruptible_timeout:和wait_event_interruptible相比,多個時間限制。在規定的時間到達後,進程恢復運行。
wait_event_interruptible_exclusive:和wait_event_interruptible區別是排他性的等待。

三. 軟中斷和tasklet

Linux內核把對應中斷的軟件執行代碼分拆成兩部分。
一部分代碼和硬件關係緊密,這部分代碼必須關閉中斷來執行,以免被後面觸發的中斷打斷,影響代碼的正確執行,這部分代碼放在中斷上下文中執行。
另一部分代碼和硬件關係不緊密,可以打開中斷執行,這部分代碼放在軟中斷上下文執行。

Linux內核定義了幾個默認的軟中斷,網絡設備有自己的發送和接收軟中斷,塊設備也有自己的軟中斷。爲了方便使用,內核還定義了一個tasklet軟中斷。tasklet是一種特殊的軟中斷同一時刻一個tasklet只能有一個CPU執行,不同的tasklet可以在不同的CPU上執行。這和軟中斷不同,軟中斷同一時刻可以在不同的CPU並行執行,因此軟中斷必須考慮重入的問題。

四. 工作隊列

工作隊列和tasklet相似,都是一種延緩執行的機制。
不同之處是工作隊列有自己的進程上下文,所以工作隊列可以睡眠,也可以被調度,而tasklet不可睡眠。

使用工作隊列很簡單,schedule_work把用戶定義的work_struct加入系統的隊列中,並喚醒系統線程去執行。那麼是哪個系統線程執行用戶的work_struct呢?實際上,內核初始化的時候,就要創建一個工作隊列keventd_wq,同事爲這個工作隊列創建內核線程(默認是爲每個CPU創建一個內核線程)。

內核同時還提供了create_workqueue和create_singlethread_workqueue函數,這樣用戶可以創建自己的工作隊列和執行線程,而不用內核提供的工作隊列。

create_workqueue和create_singlethread_workqueue類似,不同的是,create_singlethread_workqueue只創建一個內核線程,而不是爲每個CPU創建一個內核線程。

五. 自旋鎖

自旋鎖用來在多處理器的環境下保護數據。
自旋鎖可以用在中斷等禁止睡眠的場景。

六. 內核信號量

內核信號量和自旋鎖類似,作用也是保護數據。不同的是,進程獲取內核信號量的時候,如果不能獲取,則進程進入睡眠狀態。

內核信號量和自旋鎖的不同之處:

  • 內核信號量不能用在中斷處理函數和tasklet等不可睡眠的場景。
  • 深層次的原因是Linux內核以進程爲單位調度,如果在中斷上下文睡眠,中斷將不能被正確處理
  • 可睡眠的場景即可使用內核信號量,也可使用自旋鎖。自旋鎖通常用在輕量級的鎖場景。即鎖的時間很多,馬上就釋放鎖的場景。

七. 原子變量

原子變量提供了一種原子的、不可中斷的操作。
內核提供了一系列的原子變量操作函數:
atomic_add:加一個整數到原子變量。
atomic_sub:從原子變量減一個整數。
atomic_set:設置原子變量的數值。
atomic_read:讀原子變量的數組。

發佈了19 篇原創文章 · 獲贊 20 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章