Monday, January 3, 2022

[Linux Kernel] linux驅動面試題目彙總及解答

linux 驅動分類

Linux裝置驅動的分類 

(1)字元裝置

       不定長度的字元傳送資料 /dev/console

(2) 塊裝置

        固定大小長度來傳送轉移資料

        可以隨機存取 (Random Access) 資料的設備,如硬碟機或光碟機

(3) 網路裝置

自旋鎖

防止多處理器併發而引入的一種鎖,它應用於中斷處理等部分

對於單處理器來說,防止中斷處理中的併發可簡單採用關閉中斷的方式,不需要自旋鎖

自旋鎖最多只能被一個核心任務持有,如果一個核心任務試圖請求一個已被爭用(已經被持有)的自旋鎖,那麼這個任務就會一直進行忙迴圈——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的核心任務便能立刻得到它並且繼續進行。

自旋鎖可以在任何時刻防止多於一個的核心任務同時進入臨界區,防止核心搶佔造成的競爭。因此這種鎖可有效地避免多處理器上併發執行的核心任務競爭共享資源。

事實上,自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。一個被爭用的自旋鎖使得請求它的執行緒在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話, 最好使用訊號量。但是自旋鎖節省了上下文切換的開銷。

自旋鎖的基本形式如下:

spin_lock(&mr_lock);


//臨界區

spin_unlock(&mr_lock);

另外自旋鎖不允許任務睡眠(持有自旋鎖的任務睡眠會造成自死鎖——因為睡眠有可能造成持有鎖的核心任務被重新排程,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。

死鎖

所有核心任務都在相互等待,但它們永遠不會釋放已經佔有的資源

訊號量

訊號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的訊號量時,訊號量會將其推入等待佇列,然後讓其睡眠。這時處理器獲得自由去執行其它程式碼。當持有訊號量的程序將訊號量釋放後,在等待佇列中的一個任務將被喚醒,從而便可以獲得這個訊號量。

訊號量的睡眠特性,使得訊號量適用於鎖會被長時間持有的情況;只能在程序上下文中使用,因為中斷上下文中是不能被排程的;另外當代碼持有訊號量時,不可以再持有自旋鎖。

訊號量基本使用形式為:

static DECLARE_MUTEX(mr_sem);//宣告互斥訊號量

if(down_interruptible(&mr_sem))

           //可被中斷的睡眠,當訊號來到,睡眠的任務被喚醒

           //臨界區

       up(&mr_sem); 

訊號量和自旋鎖區別

如果需要在自旋鎖和訊號量中作選擇,應該取決於鎖被持有的時間長短。

理想情況是所有的鎖都應該儘可能短的被持有,但是如果鎖的持有時間較長的話,使用訊號量是更好的選擇。

另外,訊號量不同於自旋鎖,它不會關閉核心搶佔,所以持有訊號量的程式碼可以被搶佔。這意味者訊號量不會對影響排程反應時間帶來負面影響。

1. 低開銷加鎖 優先使用自旋鎖

2. 短期鎖定 優先使用自旋鎖

3. 長期加鎖 優先使用訊號量

4. 中斷上下文中加鎖 使用自旋鎖

5. 持有鎖是需要睡眠、排程 使用訊號量 

kmalloc()和vmalloc()介紹

kmalloc()

用於申請較小的、連續的實體記憶體

1. 以位元組為單位進行分配,在<linux/slab.h>中

2. void *kmalloc(size_t size, int flags) 分配的記憶體實體地址上連續,虛擬地址上自然連續

3. gfp_mask標誌:什麼時候使用哪種標誌?如下:

———————————————————————————————-

情形 相應標誌

———————————————————————————————-

程序上下文,可以睡眠 GFP_KERNEL

程序上下文,不可以睡眠 GFP_ATOMIC

中斷處理程式 GFP_ATOMIC

軟中斷 GFP_ATOMIC

Tasklet GFP_ATOMIC

用於DMA的記憶體,可以睡眠 GFP_DMA | GFP_KERNEL

用於DMA的記憶體,不可以睡眠 GFP_DMA | GFP_ATOMIC

4. void kfree(const void *ptr)

釋放由kmalloc()分配出來的記憶體塊

vmalloc()

用於申請較大的記憶體空間,虛擬記憶體是連續的

1. 以位元組為單位進行分配,在<linux/vmalloc.h>中

2. void *vmalloc(unsigned long size) 分配的記憶體虛擬地址上連續,實體地址不連續

3. 一般情況下,只有硬體裝置才需要實體地址連續的記憶體,因為硬體裝置往往存在於MMU之外,根本不瞭解虛擬地址;但為了效能上的考慮,核心中一般使用 kmalloc(),而只有在需要獲得大塊記憶體時才使用vmalloc(),例如當模組被動態載入到核心當中時,就把模組裝載到由vmalloc()分配 的記憶體上。

4.void vfree(void *addr),這個函式可以睡眠,因此不能從中斷上下文呼叫。

malloc(), vmalloc()和kmalloc()區別

[*]kmalloc和vmalloc是分配的是核心的記憶體,malloc分配的是使用者的記憶體

[*]kmalloc保證分配的記憶體在物理上是連續的,vmalloc保證的是在虛擬地址空間上的連續,malloc不保證任何東西(這點是自己猜測的,不一定正確)

[*]kmalloc能分配的大小有限,vmalloc和malloc能分配的大小相對較大

[*]記憶體只有在要被DMA訪問的時候才需要物理上連續

[*]vmalloc比kmalloc要慢

No comments:

Post a Comment

n8n index

 【n8n免費本地端部署】Windows版|程式安裝x指令大補帖  【一鍵安裝 n8n】圖文教學,獲得無限額度自動化工具&限時免費升級企業版功能