天天看點

Linux 驅動面試題總結【轉】

1、 Linux裝置中字元裝置與塊裝置有什麼主要的差別?請分别列舉一些實際的裝置說出它們是屬于哪一類裝置。

    字元裝置:字元裝置是個能夠像位元組流(類似檔案)一樣被通路的裝置,由字元裝置驅動程式來實作這種特性。字元裝置驅動程式通常至少實作open,close,read和write系統調用。字元終端、序列槽、滑鼠、鍵盤、攝像頭、聲霸卡和顯示卡等就是典型的字元裝置。

    塊裝置:和字元裝置類似,塊裝置也是通過/dev目錄下的檔案系統節點來通路。塊裝置上能夠容納檔案系統,如:u盤,SD卡,磁盤等。

    字元裝置和塊裝置的差別僅僅在于核心内部管理資料的方式,也就是核心及驅動程式之間的軟體接口,而這些不同對使用者來講是透明的。在核心中,和字元驅動程式相比,塊驅動程式具有完全不同的接口。

2、檢視驅動子產品中列印資訊應該使用什麼指令?如何檢視核心中已有的字元裝置的資訊?如何檢視正在使用的有哪些中斷号?

1) 檢視驅動子產品中列印資訊的指令:dmesg

2) 檢視字元裝置資訊可以用lsmod 和modprobe,lsmod可以檢視子產品的依賴關系,modprobe在加載子產品時會加載其他依賴的子產品。

3) 顯示目前使用的中斷号cat /proc/interrupt

3、Linux中引入子產品機制有什麼好處?

       首先,子產品是預先注冊自己以便服務于将來的某個請求,然後他的初始化函數就立即結束。換句話說,子產品初始化函數的任務就是為以後調用函數預先作準備。

好處:

1) 應用程式在退出時,可以不管資源的釋放或者其他的清除工作,但是子產品的退出函數卻必須仔細此撤銷初始化函數所作的一切。

2) 該機制有助于縮短子產品的開發周期。即:注冊和解除安裝都很靈活友善。

4、copy_to_user()和copy_from_user()主要用于實作什麼功能?一般用于file_operations結構的哪些函數裡面?

      由于核心空間和使用者空間是不能互相通路的,如果需要通路就必須借助核心函數進行資料讀寫。copy_to_user():完成核心空間到使用者空間的複制,copy_from_user():是完成使用者空間到核心空間的複制。一般用于file_operations結構裡的read,write,ioctl等記憶體資料交換作用的函數。當然,如果ioctl沒有用到記憶體資料複制,那麼就不會用到這兩個函數。

5、請簡述主裝置号和次裝置号的用途。如果執行mknod chartest c 4 64,建立chartest裝置。請分析chartest使用的是那一類裝置驅動程式。

1)主裝置号:主裝置号辨別裝置對應的驅動程式。雖然現代的linux核心允許多個驅動程式共享主裝置号,但我們看待的大多數裝置仍然按照“一個主裝置對應一個驅動程式”的原則組織。

   次裝置号:次裝置号由核心使用,用于正确确定裝置檔案所指的裝置。依賴于驅動程式的編寫方式,我們可以通過次裝置号獲得一個指向核心裝置的直接指針,也可将此裝置号當作裝置本地數組的索引。

2)chartest 由驅動程式4管理,該檔案所指的裝置是64号裝置。(感覺類似于序列槽終端或者字元裝置終端)。

6、裝置驅動程式中如何注冊一個字元裝置?分别解釋一下它的幾個參數的含義。

注冊一個字元裝置驅動有兩種方法:

1) void cdev_init(struct cdev *cdev, struct file_operations *fops)

該注冊函數可以将cdev結構嵌入到自己的裝置特定的結構中。cdev是一個指向結構體cdev的指針,而fops是指向一個類似于file_operations結構(可以是file_operations結構,但不限于該結構)的指針.

2) int register_chrdev(unsigned int major, const char *namem , struct file)operations *fopen);

該注冊函數是早期的注冊函數,major是裝置的主裝置号,name是驅動程式的名稱,而fops是預設的file_operations結構(這是隻限于file_operations結構)。對于register_chrdev的調用将為給定的主裝置号注冊0-255作為次裝置号,并為每個裝置建立一個對應的預設cdev結構。

7、請簡述中斷于DMA的差別。Linux裝置驅動程式中,使用哪個函數注冊和登出中斷處理程式?

1)DMA:是一種無須CPU的參與就可以讓外設與系統記憶體之間進行雙向資料傳輸的硬體機制,使用DMA可以使系統CPU從實際的I/O資料傳輸過程中擺脫出來,進而大大提高系統的吞吐率.

      中斷:是指CPU在執行程式的過程中,出現了某些突發事件時CPU必須暫停執行目前的程式,轉去處理突發事件,處理完畢後CPU又傳回源程式被中斷的位置并繼續執行。

     是以中斷和DMA的差別就是DMA不需CPU參與而中斷是需要CPU參與的。

2)中斷注冊函數和中斷登出函數

注冊中斷:

int request_irq(unsigned int irq, irqreturn_t (*handler)(int, void *, struct pt_regs *), unsigned long flags, const char *dev_name, void *dev_id);

參數意義依次是:中斷号,中斷處理函數,中斷管理有關的掩碼,中斷請求裝置名,中斷信号線。

過程是:dev_name裝置請求中斷->cpu配置設定中斷号->設定中斷管理的掩碼->配置設定中斷信号線->進行中斷函數->完成之後再根據設定情況傳回原處理程式處繼續處理程式。

登出中斷

Void free_irq(unsigned int irq, void *dev_id);

釋放中斷和中斷信号線

8、中斷和輪詢哪個效率高?怎樣決定是采用中斷方式還是采用輪詢方式去實作驅動?

     中斷是CPU處于被動狀态下來接受裝置的信号,而輪詢是CPU主動去查詢該裝置是否有請求。凡事都是兩面性,是以,看效率不能簡單的說那個效率高。如果是請求裝置是一個頻繁請求cpu的裝置,或者有大量資料請求的網絡裝置,那麼輪詢的效率是比中斷高。如果是一般裝置,并且該裝置請求cpu的頻率比較底,則用中斷效率要高一些。主要是看請求頻率。

9、簡單描述在cs8900的驅動設計中, 發送資料frame和接收資料frame的過程。

1)發送流程如下:

(1) 網絡裝置驅動程式從上層協定傳遞過來的sk_buff參數獲得資料包的有效資料和長度,将有效資料放入臨時緩沖區。

(2) 對于以太網,如果有效資料的長度小于以太網沖突檢測所要求的資料桢的最小長度,則給臨時緩沖區的末尾填充0

(3) 設定硬體寄存器,驅使網絡裝置進行資料發送操作。

2)接收流程

   網絡裝置接收資料主要是由中斷引發裝置的中斷處理函數,中斷處理函數判斷中斷類型,如果為接收中斷,則讀取接受到的資料,配置設定sk_buff資料結構和資料緩沖區,将接收到的資料複制到資料緩沖區,并調用netif_rx()函數将sk_buff傳遞給上層協定。

10、Cs8900.c的驅動中,發送資料frame的過程為什麼需要關中斷?接收資料frame的過程為什麼不需要關中斷?

       在發送過程中是不能被打斷的,在發送的過程中,不關中斷,這時候如果有一個中斷到來,那麼cpu有可能會去相應該中斷,如果該中斷需要改寫的資料是發送資料的緩沖區,那麼緩沖區将被改寫,這樣即使cpu相應完畢該中斷,再發送資料,接收方也不認識該資料不能接收。

      在接收資料的時候,需要打開中斷,是因為要及時的相應接收到的資料。如果關閉該中斷,那麼接收方有可能因為相應優先級高的中斷而接收不到該資料。

11、簡單描述skbuff這個資料結構在網絡結構中所起到的作用,為什麼需要一個skbuff,它的配置設定和釋放主要都在什麼部位

        sk_buff結構非常重要,它的含義為“套接字緩沖區”,用于在linux網絡子系統中的蓋層之間傳遞資料。

當發送資料包時,linux核心的網絡處理子產品必須建立一個包含要傳輸的資料包的sk_buff,然後将sk_buff遞交給下層,各層在sk_buff中添加不同的協定頭直至交給網絡裝置發送。同樣的,當網絡裝置從網絡媒介上接受到資料包後,它必須将接受到的資料轉換為sk_buff資料結構并傳遞給上層,蓋層不抛去相應的協定頭直至交給使用者。配置設定sk_buff在接受一開始就應該配置設定,在發送完畢資料之後可以釋放sk_buff

12、字元型驅動裝置怎麼建立裝置檔案

        手動建立:mknod /dev/led c 250 0    其中dev/led 為裝置節點 c 代表字元裝置 250代表主裝置号 0代表次裝置号

       還有UDEV/MDEV自動建立裝置檔案的方式,UDEV/MDEV是運作在使用者态的程式,可以動态管理裝置檔案,包括建立和删除裝置檔案,運作在使用者态意味着系統要運作之後。在  /etc/init.d/rcS 腳本檔案中會執行 mdev -s 自動建立裝置節點。

13、寫一個中斷服務需要注意哪些?如果中斷産生之後要做比較多的事情你是怎麼做的?

      中斷處理例程應該盡量短,把能放在後半段(tasklet,等待隊列等)的任務盡量放在後半段。

     寫一個中斷服務程式要注意快進快出,在中斷服務程式裡面盡量快速采集資訊,包括硬體資訊,然後退出中斷,要做其它事情可以使用工作隊列或者tasklet方式。也就是中斷上半部和下半部。

第二:中斷服務程式中不能有阻塞操作。應為中斷期間是完全占用CPU的(即不存在核心排程),中斷被阻塞住,其他程序将無法操作;

第三:中斷服務程式注意傳回值,要用定義的宏做為傳回值,而不是自己定義的OK,FAIL之類的。

14、自旋鎖和信号量在互斥使用時需要注意哪些?在中斷服務程式裡面的互斥是使用自旋鎖還是信号量?還是兩者都能用?為什麼?

      使用自旋鎖的程序不能睡眠,使用信号量的程序可以睡眠。

      中斷服務例程中的互斥使用的是自旋鎖,原因是在中斷處理例程中,硬中斷是關閉的;但是要注意這樣會丢失可能到來的中斷。

15、原子操作你怎麼了解?為了實作一個互斥,自己定義一個變量作為标記來作為一個資源隻有一個使用者行不行?

        原子操作指的是無法被打斷的操作。

        第二句話的意思是:

  定義一個變量,比如 int flag =0;

if(flag == 0)
  {
       flag = 1;


       操作臨界區;
      flag = 0;
   }      

16、insmod 一個驅動子產品,會執行子產品中的哪個函數?rmmod呢?這兩個函數在設計上要注意哪些?遇到過解除安裝驅動出現異常沒?是什麼問題引起的?

        insmod調用init函數,rmmod調用exit函數。這兩個函數在設計時要注意什麼?解除安裝子產品時曾出現解除安裝失敗的情形,原因是存在程序正在使用子產品,檢查代碼後發現産生了死鎖的問題。

      要注意在init函數中申請的資源在exit函數中要釋放,包括存儲,ioremap,定時器,工作隊列等等。也就是一個子產品注冊進核心,退出核心時要清理所帶來的影響,帶走一切不留下一點痕迹。

17、驅動中操作實體絕對位址為什麼要先ioremap?

        因為核心沒有辦法直接通路實體記憶體位址,必須先通過ioremap獲得對應的虛拟位址。

18、裝置驅動模型三個重要成員是?platfoem總線的比對規則是?在具體應用上要不要先注冊驅動再注冊裝置?有先後順序沒?

         裝置驅動模型三個重要成員是 總線、裝置、驅動;

         platfoem總線的比對規則是:要比對的裝置和驅動都要注冊;

19、linux核心裡面,記憶體申請有哪幾個函數,各自的差別?

         Kmalloc()   __get_free_page()  mempool_create()  

20、 IRQ和FIQ有什麼差別,在CPU裡面是是怎麼做的?

21

int *a;

char *b;

a 和 b本身是什麼類型?

a、b裡面本身存放的隻是一個位址,難道是這兩個位址有不同麼?

22、 中斷的上半部分和下半部分的問題:講下分成上半部分和下半部分的原因,為何要分?講下如何實作?

         上半部分執行與硬體相關的處理要求快, 而有些驅動在中斷處理程式中又需要完成大量工作,這構成沖突,是以Linux有所謂的bottom half機制,中斷處理程式中所有不要求立即完成的,在開中斷的環境下,由底半程式随後完成.

         Linux的底半處理實際上是建立在核心的軟中斷機制上的.如何實作該機制?

兩種方式

【tasklet  工作隊列】

1.定義和初始化

struct tasklet_struct tlet;

tasklet_init(&tlet, jit_tasklet_fn, (unsigned long) data);

參數

第一個:定義的tasklet變量

第二個:函數

第三個:資料  傳遞給回調函數的資料

2. 定義函數

void jit_tasklet_fn(unsigned long arg)
{
//中斷的底半部  執行該函數的時候,已經出中斷了
printk("in jit_tasklet_fn  jiffies=%ld\n",jiffies);
}      

3. 在需要排程的地方調用以下函數

tasklet_schedule(&tlet);

   一般在中斷函數當中排程在不晚于下一個時鐘滴答之前執行

【tasklet 和定期器的差別】

1. 執行時間

定時器的執行:時間是确定的

tasklet       :不确定的

2.tasklet 執行耗時的操作的

23、核心函數mmap的實作原理,機制?

         mmap函數實作把一個檔案映射到一個記憶體區域,進而我們可以像讀寫記憶體一樣讀寫檔案,他比單純調用read/write也要快上許多。在某些時候我們可以把記憶體的内容拷貝到一個檔案中實作記憶體備份,當然,也可以把檔案的内容映射到記憶體來恢複某些服務。另外,mmap實作共享記憶體也是其主要應用之一,mmap系統調用使得程序之間通過映射同一個普通檔案實作共享記憶體。

24、驅動裡面為什麼要有并發、互斥的控制?如何實作?講個例子?

25、spinlock自旋鎖是如何實作的?

       自旋鎖在同一時刻隻能被最多一個核心任務持有,是以一個時刻隻有一個線程允許存在于臨界區中。這點可以應用在多處理機器、或運作在單處理器上的搶占式核心中需要的鎖定服務。

26、信号量簡介

        這裡也介紹下信号量的概念,因為它的用法和自旋鎖有相似的地方。

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

27、 任務排程的機制?

28、什麼是GPIO?

         general purpose input/output  

         GPIO是相對于晶片本身而言的,如某個管腳是晶片的GPIO腳,則該腳可作為輸入或輸出高或低電平使用,當然某個腳具有複用的功能,即可做GPIO也可做其他用途。 也就是說你可以把這些引腳拿來用作任何一般用途的輸入輸出,例如用一根引腳連到led的一極來控制它的亮滅,也可以用一根(一些)引腳連到一個傳感器上以獲得該傳感器的狀态,這給cpu提供了一個友善的控制周邊裝置的途經。如果沒有足夠多的gpio管腳,在控制一些外圍裝置時就會力有不逮,這時可采取的方案是使用CPLD來幫助管理。

29、在Linux C中,ls這個指令是怎麼被執行的?

        使用fork建立一個程序或exec函數族覆寫原程序。

30、LINUX下的Socket套接字和Windows下的WinSock有什麼共同點?請從C/C++語言

a)都基于TCP/IP協定,都提供了面向連接配接的TCP SOCK和無連接配接的UDP SOCK。

b)都是一個sock結構體。

c)都是使用sock檔案句柄進行通路。

d)都具有緩沖機制。

31、一個計劃跑LINUX系統的ARM系統把bootloader燒錄進去後,上電後序列槽上沒有任何輸出,硬體和軟體各應該去檢查什麼?   

 提示: 1.跑LINUX的系統一般都需要外擴DRAM,一般的系統也經常有NOR或NAND FLASH