linux驅動面試題整理

1、字符型驅動設備你是怎麼創建設備文件的,就是/dev/下面的設備文件,供上層應用程序打開使用的文件?

答:mknod命令結合設備的主設備號和次設備號,可創建一個設備文件。

評:這只是其中一種方式,也叫手動創建設備文件。還有UDEV/MDEV自動創建設備文件的方式,UDEV/MDEV是運行在用戶態的程序,可以動態管理設備文件,包括創建和刪除設備文件,運行在用戶態意味着系統要運行之後。那麼在系統啓動期間還有devfs創建了設備文件。一共有三種方式可以創建設備文件。

2、寫一箇中斷服務需要注意哪些?如果中斷產生之後要做比較多的事情你是怎麼做的?
答:中斷處理例程應該儘量短,把能放在後半段(tasklet,等待隊列等)的任務儘量放在後半段。
評:寫一箇中斷服務程序要注意快進快出,在中斷服務程序裏面儘量快速採集信息,包括硬件信息,然後推出中斷,要做其它事情可以使用工作隊列或者tasklet方式。也就是中斷上半部和下半部。
第二:中斷服務程序中不能有阻塞操作。爲什麼?大家可以討論。

第三:中斷服務程序注意返回值,要用操作系統定義的宏做爲返回值,而不是自己定義的OK,FAIL之類的。

3、自旋鎖和信號量在互斥使用時需要注意哪些?在中斷服務程序裏面的互斥是使用自旋鎖還是信號量?還是兩者都能用?爲什麼?
答:使用自旋鎖的進程不能睡眠,使用信號量的進程可以睡眠。中斷服務例程中的互斥使用的是自旋鎖,原因是在中斷處理例程中,硬中斷是關閉的,這樣會丟失可能到來的中斷。

4、原子操作你怎麼理解?爲了實現一個互斥,自己定義一個變量作爲標記來作爲一個資源只有一個使用者行不行?
答:原子操作指的是無法被打斷的操作。我沒懂第二句是什麼意思,自己定義一個變量怎麼可能標記資源的使用情況?其他進程又看不見這個變量
評:第二句話的意思是:
定義一個變量,比如 int flag =0;
if(flag == 0)
{
flag = 1;
操作臨界區;
flag = 0;

}這樣可否?

5、insmod 一個驅動模塊,會執行模塊中的哪個函數?rmmod呢?這兩個函數在設計上要注意哪些?遇到過卸載驅動出現異常沒?是什麼問題引起的?
答:insmod調用init函數,rmmod調用exit函數。這兩個函數在設計時要注意什麼?卸載模塊時曾出現卸載失敗的情形,原因是存在進程正在使用模塊,檢查代碼後發現產生了死鎖的問題。

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

6、在驅動調試過程中遇到過oops沒?你是怎麼處理的?

7、ioctl和unlock_ioctl有什麼區別?

8、驅動中操作物理絕對地址爲什麼要先ioremap?
答:因爲內核沒有辦法直接訪問物理內存地址,必須先通過ioremap獲得對應的虛擬地址。

9、設備驅動模型三個重要成員是?platfoem總線的匹配規則是?在具體應用上要不要先註冊驅動再註冊設備?有先後順序沒?

10、linux中內核空間及用戶空間的區別?用戶空間與內核通信方式有哪些?

11、linux中內存劃分及如何使用?虛擬地址及物理地址的概念及彼此之間的轉化,高端內存概念?

12、linux中中斷的實現機制,tasklet與workqueue的區別及底層實現區別?爲什麼要區分上半部和下半部?

13、linux中斷的響應執行流程?中斷的申請及何時執行(何時執行中斷處理函數)?

14、linux中的同步機制?spinlock與信號量的區別?

15、linux中RCU原理?

16、linux中軟中斷的實現原理?

17、linux系統實現原子操作有哪些方法?

18、MIPS Cpu中空間地址是怎麼劃分的?如在uboot中如何操作設備的特定的寄存器?

19、linux中系統調用過程?如:應用程序中read()在linux中執行過程即從用戶空間到內核空間?

20、linux內核的啓動過程(源代碼級)?

21、linux調度原理?

22、linux網絡子系統的認識?

23、linux內核裏面,內存申請有哪幾個函數,各自的區別?
Kmalloc() __get_free_page() mempool_create()

24. IRQ和FIQ有什麼區別,在CPU裏面是是怎麼做的?

25. 中斷的上半部分和下半部分的問題:講下分成上半部分和下半部分的原因,爲何要分?講下如何實現?
上半部分執行與硬件相關的處理要求快, 而有些驅動在中斷處理程序中又需要完成大量工作,這構成矛盾,所以Linux有所謂的bottom half機制,中斷處理程序中所有不要求立即完成的,在開中斷的環境下,由底半程序隨後完成.
Linux的底半處理實際上是建立在內核的軟中斷機制上的.
Linux 的底半 機制主要有Tasklet 和 work queue 以及 softirq ( 2.4內核則有BH , Task queue , softirq , tasklet 沒有work queue),其實底半可以理解成一種工作的延遲。所以實際使用時跟timer機制基本上一個意思。

26. 內核函數mmap的實現原理,機制?
mmap函數實現把一個文件映射到一個內存區域,從而我們可以像讀寫內存一樣讀寫文件,他比單純調用read/write也要快上許多。在某些時候我們可以把內存的內容拷貝到一個文件中實現內存備份,當然,也可以把文件的內容映射到內存來恢復某些服務。另外,mmap實現共享內存也是其主要應用之一,mmap系統調用使得進程之間通過映射同一個普通文件實現共享內存。

27. 驅動裏面爲什麼要有併發、互斥的控制?如何實現?講個例子?
併發(concurrency)指的是多個執行單元同時、並行被執行,而併發的執行單元對 共 享資源(硬件資源和軟件上的全局變量、靜態變量等)的訪問則很容易導致競態(race conditions) 。 解決競態問題的途徑是保證對共享資源的互斥訪問, 所謂互斥訪問就是指一個執行單 元 在訪問共享資源的時候,其他的執行單元都被禁止訪問。 訪問共享資源的代碼區域被稱爲臨界區, 臨界區需要以某種互斥機 制加以保護, 中斷屏蔽, 原子操作,自旋鎖,和信號量都是 linux 設備驅動中可採用的互斥途徑。

28. spinlock自旋鎖是如何實現的?
自旋鎖在同一時刻只能被最多一個內核任務持有,所以一個時刻只有一個線程允許存在於臨界區中。這點可以應用在多處理機器、或運行在單處理器上的搶佔式內核中需要的鎖定服務。
  這裏也介紹下信號量的概念,因爲它的用法和自旋鎖有相似的地方。linux中的信號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然後讓其睡眠。這時處理器獲得自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而便可以獲得這個信號量。

29. 任務調度的機制?

30. 嵌入式linux和wince操作系統的特點和特性?

31. 嵌入式linux中tty設備驅動的體系結構?

32. 嵌入式設備,爲加快啓動速度,可以做哪些方面的優化?

33. USB設備的枚舉過程?
(1) Get Device Descriptor。主機的第一個命令要求得到設備描述符,此SETUP 包爲8 個字節數據(80,06,00,01,00,00,40,00),發向地址0,端口0。“40”表示返回數據長度最大爲40H 個字節。實際上,只返回一個包,即數組DEV_DESC[ ]中的前8 個字節,用於說明設備的描述符的真實長度和設備的類型。
(2) Set Address。接着是設置設備地址處理事件,主機發送一個含有指定地址的數據包(00,05,02,00,00,00,00,00),在主機只有一個USB 設備的時候,這個地址一般會是2,最大地址127,USB 協議中可以連接127 個設備。設置地址事件處理結束後,設備進入地址狀態,主機以後會在新的指定地址處訪問設備。
(3) Get Device Descriptor。主機再次發送請求得到設備描述符的數據包(80,06,00,01,00,00,12,00),與上次不同的是,要求的數據的長度是實際的數據長度,同時是發送到Set Address命令所設置的地址。
(4) 讀取全部Configuration Descriptor。接着主機要求得到設備全部的配置描述符、接口描述符和節點描述符(80,06,00,02,00,00,40,00),由於主機不知道設備描述符的真實長度,因此它要求得到64個字節。
(5) Set Interface,主機發送數據包(01,0B,00,00,00,00,00,00),設置接口值爲0。
(6) Set Conifguration,確定USB設備工作在哪一個配置下。對於U盤設備來說,一般只有1個配置值,其值爲01。主機發送數據包(00,09,01,00,00,00,00,00)。
(7) 如果以上步驟都正確,主機將找到新設備,並且配置成功,該設備可以正常使用,可以進行後續的U盤枚舉過程了。
(8) 用busHound觀察計算機對於U盤的枚舉過程,發現上述步驟後還有一個GetMaxLun的操作,但是實際上對於U盤來說忽略該步驟也沒有問題。

34. PSRAM、SDRAM、DDR、DDR2的時序特性?

35.什麼是GPIO?
general purpose input/output
GPIO是相對於芯片本身而言的,如某個管腳是芯片的GPIO腳,則該腳可作爲輸入或輸出高或低電平使用,當然某個腳具有複用的功能,即可做GPIO也可做其他用途。
也就是說你可以把這些引腳拿來用作任何一般用途的輸入輸出,例如用一根引腳連到led的一極來控制它的亮滅,也可以用一根(一些)引腳連到一個傳感器上以獲得該傳感器的狀態,這給cpu提供了一個方便的控制周邊設備的途經。如果沒有足夠多的gpio管腳,在控制一些外圍設備時就會力有不逮,這時可採取的方案是使用CPLD來幫助管理。

36.觸摸屏的硬件原理?
觸摸屏的主要三大種類是:電阻技術觸摸屏、 表面聲波技術觸摸屏、 電容技術觸摸屏。
電阻觸摸屏的主要部分是一塊與顯示器表面非常配合的電阻薄膜屏, 這是一種多層的複合薄膜,它以一層玻璃或硬塑料平板作爲基層,表面圖有一層透明氧化金屬 (ITO氧化銦,透明的導電電阻) 導電層,上面在蓋有一層外表面硬化處理、光滑防擦的塑料層 、它的內表面也塗有一層ITO塗層 、在他們之間有許多細小的(小於1/1000英寸)的透明隔離點把兩層導電層隔開絕緣 。當手指觸摸屏幕時,兩層導電層在觸摸點位置就有了接觸,控制器偵測到這一接觸並計算出(X,Y )的位置,再根據模擬鼠標的方式運作。這就是電阻技術觸摸屏的最基本的原理。
表面聲波技術是利用聲波在物體的表面進行傳輸,當有物體觸摸到表面時,阻礙聲波的傳輸,換能器偵測到這個變化,反映給計算機,進而進行鼠標的模擬。
電容技術觸摸屏利用人體的電流感應進行工作 。用戶觸摸屏幕時 ,由於人體電場,用戶和觸摸屏表面形成以一個耦合電容, 對於高頻電流來說,電容是直接導體,於是手指從接觸點吸走一個很小的電流

37.在Linux C中,ls這個命令是怎麼被執行的?
使用fork創建一個進程或exec函數族覆蓋原進程。

38.在一個只有128M內存並且沒有交換分區的機器上,說說下面兩個程序的運行結果
1

#define MEMSIZE 1024*1024
int count = 0;
void *p = NULL;
while(1) {
  p = (void *)malloc(MEMSIZE);
  if (!p) break;
  printf("Current allocation %d MB\n", ++count);
}

2

while(1) {
  p = (void *)malloc(MEMSIZE);
  if (!p) break;
  memset(p, 1, MEMSIZE);
  printf("Current allocation %d MB\n", ++count);
}

第一道程序分配內存但沒有填充,編譯器可能會把內存分配優化掉,程序死循環;第二道,程序分配內存並進行填充,系統會一直分配內存,直到內存不足,退出循環。

39.請定義一個宏,比較兩個數a、b的大小,不能使用大於、小於、if語句
搞的比較複雜。主要思想就是a-b的值的最高位是否爲0;但是又得考慮整數溢出的問題,所以很複雜。不知道哪位大俠有更好的辦法,指點指點。

#include<stdio.h>
#define ZHENG(i)((i>> 31)== 0)
#define FU(i)((i>> 31)!= 0)
#define COMPARE(a,b)((ZHENG(a)&& FU(b))||(((ZHENG(a)&& ZHENG(b))||(FU(a)&&FU(b)))&&((((a)-(b))>> 31)== 0)))
void main()
{
    int a = 0x80000001;
    int b = 0x6FFFFFFF;
    if(COMPARE(a,b))
    {
        printf("a >= b\n");
    }
    else
    {
        printf("a < b\n");
    }
}

40、LINUX下的Socket套接字和Windows下的WinSock有什麼共同點?請從C/C++語言開發的角度描述,至少說出兩點共同點。
參考答案:
第1題,答中一個得5分,答出其它正確答案的,也得5分。
a)都基於TCP/IP協議,都提供了面向連接的TCP SOCK和無連接的UDP SOCK。
b)都是一個sock結構體。
c)都是使用sock文件句柄進行訪問。
d)都具有緩衝機制。

41、請編寫一個標準Shell腳本testd,實現如下功能:
A、在Linux操作系統啓動的時候,自動加載/mnt/test/test程序。
B、當test異常退出之後,自動重新啓動。
C、當test程序重啓次數超過100次,自動復位操作系統。
假設你所擁有的資源:
A、目標機器是一臺具有標準shell的嵌入式計算機,CPU爲ARM7 56MB,內存16MB,軟件環境基於Linux2.6.11和BusyBox1.2構建。
B、當前已有11個用戶進程在運行,佔用了大部分的CPU時間和內存,你可使用的內存只有2MB左右,CPU時間由系統分派。
本題是考查LINUX和嵌入式編程功底的,寫出程序來的不少,但是95%以上的人竟無視我假設的資源,不知道在重啓test程序的時候需要加上一個適當的掩飾時間,以便資源緊張的操作系統有時間回收資源。85%的人不知道寫完testd之後,要在init裏邊加載這個腳本,才能實現啓動時自動加載的功能。
參考答案:

########################################
#testd is a daemon script to start an watch the program test
########################################
#!/bin/sh
#load *.so that may need
if [ -r /sbin/ldconfig ]; then
ldconfig
fi
#add the libs PATH that may need
export LD_LIBRARY_PATH="/lib"
#count is the counter of test started times
count=0
#main loop
while [ 1 ] ;do
#add execute property for /mnt/test/test
chmod +x /mnt/test/test
#start test
/mnt/test/test
#the running times counter
let count=count+1
echo "test running times is $count"
#Is test running too many times?
if [ "$count" -gt 100 ]; then
echo "Will reboot because of test running too many times"
reboot
fi
#wait for test stoping...

sleep 3
done
#########################################

42.你平常是怎麼用C寫嵌入式系統的死循環的?

43.寫一條命令,實現在dir以及其子目錄下找出所有包含“hello world”字符串的文件

44.下面的兩段程序中,循環能否執行?爲什麼?

A: unsigned short i; unsigned short index = 0; for(i = 0; i <index-1; i++){     printf(“a\n”); }
B: unsigned short i; unsigned long index = 0; for(i = 0; i <index-1; i++){      printf(“b\n”); }  

45.一個計劃跑LINUX系統的ARM系統把bootloader燒錄進去後,上電後串口上沒有任何輸出,硬件和軟件各應該去檢查什麼?
提示: 1.跑LINUX的系統一般都需要外擴DRAM,一般的系統也經常有NOR或NAND FLASH

476列舉最少3種你所知道的嵌入式的體系結構,並請說明什麼是ARM體系結構。

47.請簡述下面這段代碼的功能

mov r12, #0x0        

ldr r13, =0x30100000 

mov r14, #4096 

loop:   

ldmia      r12!, {r0-r11}  

stmia      r13!, {r0-r11}    

cmp       r12, r14   

bl          loop

48.嵌入式中常用的文件系統有哪些?說出它們的主要特點和應用場合?

49.某外設寄存器rGpioBase的地址是0x56000000,寄存器的015位有效,請寫出給外設寄存器高八位(8`15位)設置成0xc3的代碼

50.如何編寫一個LINUX驅動?
提示:主要說字符設備的編寫過程

51.簡述LINUX驅動中字符設備和塊設備的區別?

52.試總結單片機底層開發與LINUX驅動開發有哪些異同?

53.請從網卡、USB HOST、LCD驅動器、NAND FLASH、WIFI 、音頻芯片中選擇一個或者2個(可以以具體的芯片爲例),對下面的問題做答:
1)如果是外部擴展芯片,請說出你用的芯片的型號
2)畫出上題中你選定相應硬件模塊與CPU的主要引腳連線
3) 編寫上題中你選定相應硬件模塊相應LINUX驅動的流程?

54、linux驅動分類

Linux設備驅動的分類
  (1)字符設備。
  (2) 塊設備。
  (3) 網絡設備。
  字符設備指那些必須以串行順序依次進行訪問的設備,如觸摸屏、磁帶驅動器、鼠標等。塊設備可以用任意順序進行訪問,以塊爲單位進行操作,如硬盤、軟驅等。字符設備不經過系統的快速緩衝,而塊設備經過系統的快速緩衝。但是,字符設備和塊設備並沒有明顯的界限,如對於Flash設備,符合塊設備的特點,但是我們仍然可以把它作爲一個字符設備來訪問。網絡設備在Linux裏做專門的處理。Linux的網絡系統主要是基於BSD unix的socket 機制。在系統和驅動程序之間定義有專門的數據結構(sk_buff)進行數據的傳遞。系統裏支持對發送數據和接收數據的緩存,提供流量控制機制,提供對多協議的支持。

55、信號量與自旋鎖

自旋鎖
  自旋鎖是專爲防止多處理器併發而引入的一種鎖,它應用於中斷處理等部分。對於單處理器來說,防止中斷處理中的併發可簡單採用關閉中斷的方式,不需要自旋鎖。
  自旋鎖最多隻能被一個內核任務持有,如果一個內核任務試圖請求一個已被爭用(已經被持有)的自旋鎖,那麼這個任務就會一直進行忙循環——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的內核任務便能立刻得到它並且繼續進行。自旋鎖可以在任何時刻防止多於一個的內核任務同時進入臨界區,因此這種鎖可有效地避免多處理器上併發運行的內核任務競爭共享資源。
  事實上,自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。一個被爭用的自旋鎖使得請求它的線程在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話, 最好使用信號量。但是自旋鎖節省了上下文切換的開銷。
自旋鎖的基本形式如下:
  spin_lock(&mr_lock);
  //臨界區
  spin_unlock(&mr_lock);
  因爲自旋鎖在同一時刻只能被最多一個內核任務持有,所以一個時刻只有一個線程允許存在於臨界區中。這點很好地滿足了對稱多處理機器需要的鎖定服務。在單處理器上,自旋鎖僅僅當作一個設置內核搶佔的開關。如果內核搶佔也不存在,那麼自旋鎖會在編譯時被完全剔除出內核。
  簡單的說,自旋鎖在內核中主要用來防止多處理器中併發訪問臨界區,防止內核搶佔造成的競爭。另外自旋鎖不允許任務睡眠(持有自旋鎖的任務睡眠會造成自死鎖——因爲睡眠有可能造成持有鎖的內核任務被重新調度,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。
死鎖:假設有一個或多個內核任務和一個或多個資源,每個內核都在等待其中的一個資源,但所有的資源都已經被佔用了。這便會發生所有內核任務都在相互等待,但它們永遠不會釋放已經佔有的資源,於是任何內核任務都無法獲得所需要的資源,無法繼續運行,這便意味着死鎖發生了。自死瑣是說自己佔有了某個資源,然後自己又申請自己已佔有的資源,顯然不可能再獲得該資源,因此就自縛手腳了。遞歸使用一個自旋鎖就會出現這種情況。

信號量
信號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然後讓其睡眠。這時處理器獲得自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而便可以獲得這個信號量。
  信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的情況;只能在進程上下文中使用,因爲中斷上下文中是不能被調度的;另外當代碼持有信號量時,不可以再持有自旋鎖。
信號量基本使用形式爲:
  static DECLARE_MUTEX(mr_sem);//聲明互斥信號量
  if(down_interruptible(&mr_sem))
//可被中斷的睡眠,當信號來到,睡眠的任務被喚醒
//臨界區
up(&mr_sem);

信號量和自旋鎖區別
  從嚴格意義上講,信號量和自旋鎖屬於不同層次的互斥手段,前者的實現有賴於後者。
注意以下原則:
如果代碼需要睡眠——這往往是發生在和用戶空間同步時——使用信號量是唯一的選擇。由於不受睡眠的限制,使用信號量通常來說更加簡單一些。如果需要在自旋鎖和信號量中作選擇,應該取決於鎖被持有的時間長短。理想情況是所有的鎖都應該儘可能短的被持有,但是如果鎖的持有時間較長的話,使用信號量是更好的選擇。另外,信號量不同於自旋鎖,它不會關閉內核搶佔,所以持有信號量的代碼可以被搶佔。這意味者信號量不會對影響調度反應時間帶來負面影響。

自旋鎖對信號量
需求              建議的加鎖方法
低開銷加鎖           優先使用自旋鎖
短期鎖定            優先使用自旋鎖
長期加鎖            優先使用信號量
中斷上下文中加鎖        使用自旋鎖
持有鎖是需要睡眠、調度     使用信號量

56、platform總線設備及總線設備如何編寫

57、kmalloc和vmalloc的區別

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要慢

58、module_init的級別

59、添加驅動

靜態加載和動態加載:
靜態加載是系統啓動的時候由內核自動加載的,這個要事先將驅動編譯進內核才行;
動態加載,也就是模塊加載方式,這種方式下驅動以模塊的形式存放在文件系統中,需要時動態載入內核,這種主要用在調試的時候,比較方便靈活。insmod module.ko

60、IIC原理,總線框架,設備編寫方法,i2c_msg

61、kernel panic

62、USB總線,USB傳輸種類,urb等

USB總線:
USB總線屬於一種輪詢式總線,主機控制端口初始化所有的數據傳輸。每一總線動作最多傳送三個數據包,包括令牌(Token)、數據(Data)、聯絡(HandShake)。按照傳輸前制定好的原則,在每次傳送開始時,主機送一個描述傳輸動作的種類、方向、USB設備地址和終端號的USB數據包,這個數據包通常被稱爲令牌包(TokenPacket)。USB設備從解碼後的數據包的適當位置取出屬於自己的數據。數據傳輸方向不是從主機到設備就是從設備到主機。在傳輸開始時,由標誌包來標誌數據的傳輸方向,然後發送端開始發送包含信息的數據包或表明沒有數據傳送。接收端也要相應發送一個握手的數據包表明是否傳送成功。發送端和接收端之間的USB數據傳輸,在主機和設備的端口之間,可視爲一個通道。USB中有一個特殊的通道一缺省控制通道,它屬於消息通道,設備一啓動即存在,從而爲設備的設置、狀態查詢和輸入控制信息提供一個入口。

USB總線的四種傳輸類型:
1、中斷傳輸:由OUT事務和IN事務構成,用於鍵盤、鼠標等HID設備的數據傳輸中 2、批量傳輸:由OUT事務和IN事務構成,用於大容量數據傳輸,沒有固定的傳輸速率,也不佔用帶寬,當總線忙時,USB會優先進行其他類型的數據傳輸,而暫時停止批量轉輸。 3、同步傳輸:由OUT事務和IN事務構成,有兩個特別地方,第一,在同步傳輸的IN和OUT事務中是沒有返回包階段的;第二,在數據包階段任何的數據包都爲DATA0 4、控制傳輸:最重要的也是最複雜的傳輸,控制傳輸由三個階段構成(初始配置階段、可選數據階段、狀態信息步驟),每一個階段能夠看成一個的傳輸,也就是說控制傳輸其實是由三個傳輸構成的,用來於USB設備初次加接到主機之後,主機通過控制傳輸來交換信息,設備地址和讀取設備的描述符,使得主機識別設備,並安裝相應的驅動程式,這是每一個USB研發者都要關心的問題。
URB:
USB請求塊(USB request block,urb)是USB設備驅動中用來描述與USB設備通信所用的基本載體和核心數據結構,非常類似於網絡設備驅動中的sk_buff結構體,是USB主機與設備通信的“電波”。
63、同步和互斥
同步和互斥
  相交進程之間的關係主要有兩種,同步與互斥。所謂互斥,是指散步在不同進程之間的若干程序片斷,當某個進程運行其中一個程序片段時,其它進程就不能運行它們之中的任一程序片段,只能等到該進程運行完這個程序片段後纔可以運行。所謂同步,是指散步在不同進程之間的若干程序片斷,它們的運行必須嚴格按照規定的某種先後次序來運行,這種先後次序依賴於要完成的特定的任務。
  顯然,同步是一種更爲複雜的互斥,而互斥是一種特殊的同步。也就是說互斥是兩個線程之間不可以同時運行,他們會相互排斥,必須等待一個線程運行完畢,另一個才能運行,而同步也是不能同時運行,但他是必須要安照某種次序來運行相應的線程(也是一種互斥)!
總結:
  互斥:是指某一資源同時只允許一個訪問者對其進行訪問,具有唯一性和排它性。但互斥無法限制訪問者對資源的訪問順序,即訪問是無序的。
  同步:是指在互斥的基礎上(大多數情況),通過其它機制實現訪問者對資源的有序訪問。在大多數情況下,同步已經實現了互斥,特別是所有寫入資源的情況必定是互斥的。少數情況是指可以允許多個訪問者同時訪問資源

64、 Linux設備中字符設備與塊設備有什麼主要的區別?請分別列舉一些實際的設備說出它們是屬於哪一類設備。
答:字符設備:字符設備是個能夠像字節流(類似文件)一樣被訪問的設備,由字符設備驅動程序來實現這種特性。字符設備驅動程序通常至少實現open,close,read和write系統調用。字符終端、串口、鼠標、鍵盤、攝像頭、聲卡和顯卡等就是典型的字符設備。
塊設備:和字符設備類似,塊設備也是通過/dev目錄下的文件系統節點來訪問。塊設備上能夠容納文件系統,如:u盤,SD卡,磁盤等。
字符設備和塊設備的區別僅僅在於內核內部管理數據的方式,也就是內核及驅動程序之間的軟件接口,而這些不同對用戶來講是透明的。在內核中,和字符驅動程序相比,塊驅動程序具有完全不同的接口

65、查看驅動模塊中打印信息應該使用什麼命令?如何查看內核中已有的字符設備的信息?如何查看正在使用的有哪些中斷號?
答:1) 查看驅動模塊中打印信息的命令:dmesg
2) 查看字符設備信息可以用lsmod 和modprobe,lsmod可以查看模塊的依賴關係,modprobe在加載模塊時會加載其他依賴的模塊。
3)顯示當前使用的中斷號cat /proc/interrupt

66、Linux中引入模塊機制有什麼好處?
答:首先,模塊是預先註冊自己以便服務於將來的某個請求,然後他的初始化函數就立即結束。換句話說,模塊初始化函數的任務就是爲以後調用函數預先作準備。
好處:
1) 應用程序在退出時,可以不管資源的釋放或者其他的清除工作,但是模塊的退出函數卻必須仔細此撤銷初始化函數所作的一切。
2) 該機制有助於縮短模塊的開發週期。即:註冊和卸載都很靈活方便。

67、copy_to_user()和copy_from_user()主要用於實現什麼功能?一般用於file_operations結構的哪些函數裏面?
答:由於內核空間和用戶空間是不能互相訪問的,如果需要訪問就必須藉助內核函數進行數據讀寫。copy_to_user():完成內核空間到用戶空間的複製,copy_from_user():是完成用戶空間到內核空間的複製。一般用於file_operations結構裏的read,write,ioctl等內存數據交換作用的函數。當然,如果ioctl沒有用到內存數據複製,那麼就不會用到這兩個函數。

68、請簡述主設備號和次設備號的用途。如果執行mknod chartest c 4 64,創建chartest設備。請分析chartest使用的是那一類設備驅動程序。
答:
1)主設備號:主設備號標識設備對應的驅動程序。雖然現代的linux內核允許多個驅動程序共享主設備號,但我們看待的大多數設備仍然按照“一個主設備對應一個驅動程序”的原則組織。
次設備號:次設備號由內核使用,用於正確確定設備文件所指的設備。依賴於驅動程序的編寫方式,我們可以通過次設備號獲得一個指向內核設備的直接指針,也可將此設備號當作設備本地數組的索引。
2)chartest 由驅動程序4管理,該文件所指的設備是64號設備。(感覺類似於串口終端或者字符設備終端)。

69、設備驅動程序中如何註冊一個字符設備?分別解釋一下它的幾個參數的含義。
答:註冊一個字符設備驅動有兩種方法:
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結構。

70、請簡述中斷與DMA的區別。Linux設備驅動程序中,使用哪個函數註冊和註銷中斷處理程序?
答:1)DMA:是一種無須CPU的參與就可以讓外設與系統內存之間進行雙向數據傳輸的硬件機制,使用DMA可以使系統CPU從實際的I/O數據傳輸過程中擺脫出來,從而大大提高系統的吞吐率。
中斷:是指CPU在執行程序的過程中,出現了某些突發事件時CPU必須暫停執行當前的程序,轉去處理突發事件,處理完畢後CPU又返回源程序被中斷的位置並繼續執行。
所以中斷和MDA的區別就是MDA不需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);
釋放中斷和中斷信號線

71、中斷和輪詢哪個效率高?怎樣決定是採用中斷方式還是採用輪詢方式去實現驅動?
答:中斷是CPU處於被中狀態下來接受設備的信號,而輪詢是CPU主動去查詢該設備是否有請求。凡事都是兩面性,所以,看效率不能簡單的說那個效率高。如果是請求設備是一個頻繁請求cpu的設備,或者有大量數據請求的網絡設備,那麼輪詢的效率是比中斷高。如果是一般設備,並且該設備請求cpu的頻率比較底,則用中斷效率要高一些。

72、簡單描述在cs8900的驅動設計中, 發送數據frame和接收數據frame的過程。
答:1)發送流程如下:
(1) 網絡設備驅動程序從上層協議傳遞過來的sk_buff參數獲得數據包的有效數據和長度,將有效數據放入臨時緩衝區。
(2) 對於以太網,如果有效數據的長度小於以太網衝突檢測所要求的數據楨的最小長度,則給臨時緩衝區的末尾填充0
(3) 設置硬件寄存器,驅使網絡設備進行數據發送操作。
2)接收流程
網絡設備接收數據主要是由中斷引發設備的中斷處理函數,中斷處理函數判斷中斷類型,如果爲接收中斷,則讀取接受到的數據,分配sk_buff數據結構和數據緩衝區,將接收到的數據複製到數據緩衝區,並調用netif_rx()函數將sk_buff傳遞給上層協議。

73、cs8900.c的驅動中,發送數據frame的過程爲什麼需要關中斷?接收數據frame的過程爲什麼不需要關中斷?
答:在發送過程中是不能被打斷的,在發送的過程中,不關中斷,這時候如果有一箇中斷到來,那麼cpu有可能會去相應該中斷,如果該中斷需要改寫的數據是發送數據的緩衝區,那麼緩衝區將被改寫,這樣即使cpu相應完畢該中斷,再發送數據,接收方也不認識該數據不能接收。
在接收數據的時候,需要打開中斷,是因爲要及時的相應接收到的數據。如果關閉該中斷,那麼接收方有可能因爲相應優先級高的中斷而接收不到該數據。

74、簡單描述skbuff這個數據結構在網絡結構中所起到的作用,爲什麼需要一個skbuff,它的分配和釋放主要都在什麼部位
答:sk_buff結構非常重要,它的含義爲“套接字緩衝區”,用於在linux網絡子系統中的各層之間傳遞數據。
當發送數據包時,linux內核的網絡處理模塊必須建立一個包含要傳輸的數據包的sk_buff,然後將sk_buff遞交給下層,各層在sk_buff中添加不同的協議頭直至交給網絡設備發送。同樣的,當網絡設備從網絡媒介上接受到數據包後,它必須將接受到的數據轉換爲sk_buff數據結構並傳遞給上層,蓋層不拋去相應的協議頭直至交給用戶。分配sk_buff在接收一開始就應該分配,在發送完畢數據之後可以釋放sk_buff。

linux driver面試題 1

[預處理器(Preprocessor)]

  1. 用預處理指令#define 聲明一個常數,用以表明1年中有多少秒(忽略閏年問題)

#define SECONDS_PER_YEAR (60 * 60 * 24 *365)UL

我在這想看到幾件事情:

1). #define 語法的基本知識(例如:不能以分號結束,括號的使用,等等)

2). 懂得預處理器將爲你計算常數表達式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。

3). 意識到這個表達式將使一個16位機的整型數溢出-因此要用到長整型符號L,告訴編譯器這個常數是的長整型數。

4). 如果你在你的表達式中用到UL(表示無符號長整型),那麼你有了一個好的起點。記住,第一印象很重要。

  1. 寫一個“標準”宏MIN,這個宏輸入兩個參數並返回較小的一個。

#define MIN(A,B) ((A) <(B) ?(A) :(B))

C\C++試題集 C\C++ Development這個測試是爲下面的目的而設的:

1). 標識#define在宏中應用的基本知識。這是很重要的,因爲直到嵌入(inline)操作符變爲標準C的一部分,宏是方便產生嵌入代碼的唯一方法,對於嵌入式系統來說,爲了能達到要求的性能,嵌入代碼經常是必須的方法。

2). 三重條件操作符的知識。這個操作符存在C語言中的原因是它使得編譯器能產生比if-then-else更優化的代碼,瞭解這個用法是很重要的。

3). 懂得在宏中小心地把參數用括號括起來

4). 我也用這個問題開始討論宏的副作用,例如:當你寫下面的代碼時會發生什麼事?

Least = MIN(*p++, b);

  1. 預處理器標識#error的目的是什麼?

停止編譯並顯示出錯誤信息

[死循環(Infinite loops)]

  1. 嵌入式系統中經常要用到無限循環,你怎麼樣用C編寫死循環呢?

這個問題用幾個解決方案。我首選的方案是:

while(1) { }

一些程序員更喜歡如下方案:

for(;😉 { }

這個實現方式讓我爲難,因爲這個語法沒有確切表達到底怎麼回事。如果一個應試者給出這個作爲方案,我將用這個作爲一個機會去探究他們這樣做的

基本原理。如果他們的基本答案是:“我被教着這樣做,但從沒有想到過爲什麼。”這會給我留下一個壞印象。

第三個方案是用 goto

Loop:

goto Loop;

應試者如給出上面的方案,這說明或者他是一個彙編語言程序員(這也許是好事)或者他是一個想進入新領域的BASIC/FORTRAN程序員。

[數據聲明(Data declarations)]

  1. 用變量a給出下面的定義

a) 一個整型數(An integer)

b) 一個指向整型數的指針(A pointerto an integer)

c) 一個指向指針的的指針,它指向的指針是指向一個整型數(A pointer to a pointer to an integer)

d) 一個有10個整型數的數組(Anarray of 10 integers)

e) 一個有10個指針的數組,該指針是指向一個整型數的(An array of 10 pointers to integers)

f) 一個指向有10個整型數數組的指針(Apointer to an array of 10 integers)

g) 一個指向函數的指針,該函數有一個整型參數並返回一個整型數(A pointer to a function that takes an integer as an argument andreturns an integer)

h) 一個有10個指針的數組,該指針指向一個函數,該函數有一個整型參數並返回一個整型數( An array of ten pointers to functions that take an integer argumentand return an integer )

答案是:

a) int a; // An integer

b) int *a; // A pointer to an integer

c) int **a; // A pointer to a pointer to aninteger

d) int a[10]; // An array of 10 integers

e) int *a[10]; // An array of 10 pointersto integers

f) int (*a)[10]; // A pointer to an arrayof 10 integers

g) int (*a)(int); // A pointer to afunction a that takes an integer argument and returns an integer

h) int (*a[10])(int); // An array of 10pointers to functions that take an integer argument and return an integer

人們經常聲稱這裏有幾個問題是那種要翻一下書才能回答的問題,我同意這種說法。當我寫這篇文章時,爲了確定語法的正確性,我的確查了一下書。

但是當我被面試的時候,我期望被問到這個問題(或者相近的問題)。因爲在被面試的這段時間裏,我確定我知道這個問題的答案。應試者如果不知道

所有的答案(或至少大部分答案),那麼也就沒有爲這次面試做準備,如果該面試者沒有爲這次面試做準備,那麼他又能爲什麼出準備呢?

[Static]

  1. 關鍵字static的作用是什麼?

這個簡單的問題很少有人能回答完全。在C語言中,關鍵字static有三個明顯的作用:

1). 在函數體,一個被聲明爲靜態的變量在這一函數被調用過程中只會初始化一次。

2). 在模塊內(但在函數體外),一個被聲明爲靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。

3). 在模塊內,一個被聲明爲靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地範圍內使用。

大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個應試者的嚴重的缺點,因爲他顯然不懂得本地化數據和代碼範圍的好處和重要性。

linux驅動面試題2

1.什麼是GPIO?

general purpose input/output

GPIO是相對於芯片本身而言的,如某個管腳是芯片的GPIO腳,則該腳可作爲輸入或輸出高或低電平使用,當然某個腳具有複用的功能,即可做GPIO也可做其他用途。

也就是說你可以把這些引腳拿來用作任何一般用途的輸入輸出,例如用一根引腳連到led的一極來控制它的亮滅,也可以用一根(一些)引腳連到一個傳感器上以獲得該傳感器的狀態,這給cpu提供了一個方便的控制周邊設備的途經。如果沒有足夠多的gpio管腳,在控制一些外圍設備時就會力有不逮,這時可採取的方案是使用CPLD來幫助管理。

2.觸摸屏的硬件原理?

http://www.51touch.com/Article/Maintain/Technology/175945932.htm

http://www.cublog.cn/u2/78837/showart_1186312.html

觸摸屏的主要三大種類是:電阻技術觸摸屏、 表面聲波技術觸摸屏、 電容技術觸摸屏。

電阻觸摸屏的主要部分是一塊與顯示器表面非常配合的電阻薄膜屏, 這是一種多層的複合薄膜,它以一層玻璃或硬塑料平板作爲基層,表面圖有一層透明氧化金屬 (ITO氧化銦,透明的導電電阻) 導電層,上面在蓋有一層外表面硬化處理、光滑防擦的塑料層 、它的內表面也塗有一層ITO塗層 、在他們之間有許多細小的(小於1/1000英寸)的透明隔離點把兩層導電層隔開絕緣 。當手指觸摸屏幕時,兩層導電層在觸摸點位置就有了接觸,控制器偵測到這一接觸並計算出(X,Y )的位置,再根據模擬鼠標的方式運作。這就是電阻技術觸摸屏的最基本的原理。

表面聲波技術是利用聲波在物體的表面進行傳輸,當有物體觸摸到表面時,阻礙聲波的傳輸,換能器偵測到這個變化,反映給計算機,進而進行鼠標的模擬。
電容技術觸摸屏利用人體的電流感應進行工作 。用戶觸摸屏幕時 ,由於人體電場,用戶和觸摸屏表面形成以一個耦合電容, 對於高頻電流來說,電容是直接導體,於是手指從接觸點吸走一個很小的電流

3.在Linux C中,ls這個命令是怎麼被執行的?

使用fork創建一個進程或exec函數族覆蓋原進程。

4.在一個只有128M內存並且沒有交換分區的機器上,說說下面兩個程序的運行結果
1,

#define MEMSIZE 1024*1024
int count = 0;
void *p = NULL;
while(1) {
  p = (void *)malloc(MEMSIZE);
  if (!p) break;
  printf("Current allocation %d MB\n", ++count);
}

2,

while(1) {
  p = (void *)malloc(MEMSIZE);
  if (!p) break;
  memset(p, 1, MEMSIZE);
  printf("Current allocation %d MB\n", ++count);
}

第一道程序分配內存但沒有填充,編譯器可能會把內存分配優化掉,程序死循環;第二道,程序分配內存並進行填充,系統會一直分配內存,直到內存不足,退出循環。

5.請定義一個宏,比較兩個數a、b的大小,不能使用大於、小於、if語句
搞的比較複雜。主要思想就是a-b的值的最高位是否爲0;但是又得考慮整數溢出的問題,所以很複雜。不知道哪位大俠有更好的辦法,指點指點。

#include<stdio.h>
#define ZHENG(i)((i>> 31)== 0)
#define FU(i)((i>> 31)!= 0)
#define COMPARE(a,b)((ZHENG(a)&& FU(b))||(((ZHENG(a)&& ZHENG(b))||(FU(a)&&FU(b)))&&((((a)-(b))>> 31)== 0)))
void main()
{
    int a = 0x80000001;
    int b = 0x6FFFFFFF;
    if(COMPARE(a,b))
    {
        printf("a >= b\n");
    }
    else
    {
        printf("a < b\n");
    }
}

1、LINUX下的Socket套接字和Windows下的WinSock有什麼共同點?請從C/C++語言開發的角度描述,至少說出兩點共同點。(10分,說得好的每點加5分,沒有上限。精通SOCK編程者破格錄用。)

本題的目的就是考考應試者的SOCK功底,以及應用能力。答案可謂是五花八門,但是答對的少得可憐。其實答案很多,也很好回答。可見面試者功底確實一般,對SOCK編程只是一知半解。更有甚者,把TCP/IP的原理搬出來講了一大堆,卻無一條符合要求。

參考答案:

第1題,答中一個得5分,答出其它正確答案的,也得5分。

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

b)都是一個sock結構體。

c)都是使用sock文件句柄進行訪問。

d)都具有緩衝機制。

2、請編寫一個標準Shell腳本testd,實現如下功能:

A、在Linux操作系統啓動的時候,自動加載/mnt/test/test程序。

B、當test異常退出之後,自動重新啓動。

C、當test程序重啓次數超過100次,自動復位操作系統。

假設你所擁有的資源:

A、目標機器是一臺具有標準shell的嵌入式計算機,CPU爲ARM7 56MB,內存16MB,軟件環境基於Linux2.6.11和BusyBox1.2構建。

B、當前已有11個用戶進程在運行,佔用了大部分的CPU時間和內存,你可使用的內存只有2MB左右,CPU時間由系統分派。

(本題滿分20分,程序15分,註釋5分。程序不能運行的0分,能夠運行但有BUG的10分,能夠正確無誤的運行的15分。清楚編寫註釋的5分。)

本題是考查LINUX和嵌入式編程功底的,寫出程序來的不少,但是95%以上的人竟無視我假設的資源,不知道在重啓test程序的時候需要加上一個適當的
掩飾時間,以便資源緊張的操作系統有時間回收資源。85%的人不知道寫完testd之後,要在init裏邊加載這個腳本,才能實現啓動時自動加載的功能。
有人甚至在腳本開頭使用bash作爲腳本解析器,我已經清清楚楚說明了用“標準shell”!用sh不就完了嗎?是習慣作祟嗎?

參考答案:

########################################

#testd is a daemon script to start an watch the program test

########################################

#!/bin/sh



#load *.so that may need

if [ -r /sbin/ldconfig ]; then

ldconfig

fi



#add the libs PATH that may need

export LD_LIBRARY_PATH="/lib"



#count is the counter of test started times

count=0



#main loop

while [ 1 ] ;do

#add execute property for /mnt/test/test

chmod +x /mnt/test/test

#start test

/mnt/test/test

#the running times counter

let count=count+1

echo "test running times is $count"

#Is test running too many times?

if [ "$count" -gt 100 ]; then

echo "Will reboot because of test running too many times"

reboot

fi

#wait for test stoping...

sleep 3

done

#########################################

就業模擬測試題-LINUX驅動、系統底層工程師職位 1.你平常是怎麼用C寫嵌入式系統的死循環的? [3分] 2.寫一條命令,實現在dir以及其子目錄下找出所有包含“hello world”字符串的文件[2分]

3.下面的兩段程序中,循環能否執行?爲什麼?

A: unsigned short i; unsigned short index = 0; for(i = 0; i <index-1; i++){     printf(“a\n”); }
B: unsigned short i; unsigned long index = 0; for(i = 0; i <index-1; i++){      printf(“b\n”); }  

4.一個計劃跑LINUX系統的ARM系統把bootloader燒錄進去後,上電後串口上沒有任何輸出,硬件和軟件各應該去檢查什麼?

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

2.bootloader一般是由彙編和C編寫的裸奔程序[5分]

5.列舉最少3種你所知道的嵌入式的體系結構,並請說明什麼是ARM體系結構。[7分]

6.請簡述下面這段代碼的功能 mov r12, #0x0 ldr r13, =0x30100000 mov r14, #4096 loop: ldmia r12!, {r0-r11} stmia r13!, {r0-r11} cmp r12, r14 blo loop [2分]

7.嵌入式中常用的文件系統有哪些?說出它們的主要特點和應用場合?[5分]

8.某外設寄存器rGpioBase的地址是0x56000000,寄存器的015位有效,請寫出給外設寄存器高八位(8`15位)設置成0xc3的代碼[7分]

9.根據時序圖和說明編寫程序:

GPIO已經設置好,只需要調用函數gpio_seet_level(int gpio, int level)即課使某個GPIO輸出高電平或者低電平。圖中用於產生時序的gpio已經分別定義爲SSP_XCS,SSP_SCLK,SSP_DIN,level的定義分別爲GPIO_LO和GPIO_HI,需要編寫函數的原型爲:void ssp_io_write_word(u32 command),該函數用來輸出一個字(如上圖中的A0到C0一組9位),這9個位是在參數command中的低9位. [5分] 10.簡述LINUX系統從上電開始到系統起來的主要流程? 提示: 1.可以uboot、內核和文件系統的主要功能去總結.2.這個題主要是在筆試之後的面試,需要在3~5分鐘之內表述清楚[8分]

11.如何編寫一個LINUX驅動?

提示:主要說字符設備的編寫過程 [7分] 12.簡述LINUX驅動中字符設備和塊設備的區別?[5分]

13.試總結單片機底層開發與LINUX驅動開發有哪些異同?[4分]

14.請從網卡、USB HOST、LCD驅動器、NAND FLASH、WIFI 、音頻芯片中選擇一個或者2個(可以以具體的芯片爲例),對下面的問題做答:
1.如果是外部擴展芯片,請說出你用的芯片的型號
[每空5分]

15.畫出上題中你選定相應硬件模塊與CPU的主要引腳連線[5分] 16. 編寫上題中你選定相應硬件模塊相應LINUX驅動的流程?[6分]

int *ptr = (int *)0xaa66; *ptr = 0x67a9;
我感覺自己寫的應該不算錯吧(自我感覺,還請達人指正),我寫的適合裸機下用,當做寄存器用,而答案就是適合在操作系統下的寫法。

  1. linux內核裏面,內存申請有哪幾個函數,各自的區別?

  2. IRQ和FIQ有什麼區別,在CPU裏面是是怎麼做的? 3.
    int *a;
    char *b;
    a 和 b本身是什麼類型?
    a、b裏面本身存放的只是一個地址,難道是這兩個地址有不同麼?

  3. 中斷的上半部分和下半部分的問題:
    講下分成上半部分和下半部分的原因,爲何要分?講下如何實現?

  4. 內核函數mmap的實現原理,機制?

  5. 驅動裏面爲什麼要有併發、互斥的控制?如何實現?講個例子?

  6. spinlock自旋鎖是如何實現的?

  7. 任務調度的機制?
    【二、本人碰到】

  8. 嵌入式linux和wince操作系統的特點和特性?

  9. 嵌入式linux中tty設備驅動的體系結構?

  10. 嵌入式設備,爲加快啓動速度,可以做哪些方面的優化?

  11. USB設備的枚舉過程?

  12. PSRAM、SDRAM、DDR、DDR2的時序特性?

  13. I2C觸摸屏芯片與CPU的數據傳輸流程?畫出相關圖例?(這題目記得不是太清楚了,大概是考查I2C設備驅動的數據傳輸過程)

1、linux驅動分類

2、信號量與自旋鎖

3、platform總線設備及總線設備如何編寫

4、kmalloc和vmalloc的區別

5、module_init的級別

6、添加驅動

7、IIC原理,總線框架,設備編寫方法,i2c_msg

8、kernel panic

9、USB總線,USB傳輸種類,urb等

10、android boot 流程

11、android init解析init.rc

驅動工程師 筆試題

一、選擇題

1:main()
{ int x=1,y=1;
  y=x-- ;
  printf( “ %d,%d\n ”,x,y);
}運行結果爲( ) ;
A.0 , 0 B.0 , 1
C.1 , 0 D.1 , 1

2:某文件中定義的靜態全局變量(或稱靜態外部變量)其作用域是( )
A.只限某個函數 B.本文件
C.跨文件 D.不限制作用域

3:設 int a[10],p=a ;則對數組元素的正確引用是( )
A.a[p] B.p[a]
C.
(p+2) D.p+2

4:C語言中,系統自動打開的文件是( )
A.二進制文件 B.隨機文件
C.非緩衝文件 D.設備文件

5:下列程序的運行結果是( )

main( )
{ int a[][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int (*p)[4],i=2,j=1;

p=a;

printf(″%d\n″,((p+i)+j));

}
A.9 B.11 C.17 D.19

6:在軟件生命週期中,下列哪個說法是不準確的?( )
A.軟件生命週期分爲計劃、開發和運行三個階段
B.在計劃階段要進行問題確認和需求分析
C.在開發後期才能進行編寫代碼和軟件測試
D.在運行階段主要是進行軟件維護

7:下列語句定義整型指針p1、p2,( ) 是正確的。
A.int p1,p2; B.int*p1,*p2;
C.int *p1,p2; D.int**p1,p2;

8:下列程序的運行結果是( )

main()
{
int a[5] = {1,2,3,4,5};
int ptr = (int)(&a+1);

printf("%d %d" , (a+1),(ptr-1) );

}
A. 2 2 B. 2 1
C.2 5 D.以上均不是

二、簡答題

8、下面的程序或程序段存在一個錯誤或不妥處請在其下劃一條線,並將改正的內容寫到每小題後的空白處
main()
{ char cl,c2;
  cl=‘9’;
  c2=‘10’;
  printf(”cl=%c,c2=%c\n”,c1,c2);
}

9、下面的代碼輸出是什麼,爲什麼?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}

10、中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提供一種擴展 ―讓標準 C支持中斷。具代表事實是,產生了一個新的關鍵字__interrupt,下面的代碼就使用了 __interrupt關鍵字去定義了一箇中斷服務子程序 (ISR),請評論一下這段代碼,找出錯誤並改正.

__interruptdouble compute_area (double radius)

{

doublearea = PI * radius * radius;

printf("\nArea= %f", area);

returnarea;

}

三、內核驅動題

11、請簡述arm linux內核啓動流程。

12、驅動裏面爲什麼要有併發、互斥的控制?如何實現?舉例說明。

13、請簡述linux內核終端處理分成上半部分和下半部分的原因,爲何要分?如何實現?

四、編程實現題

14、設計並實現一個在linux平臺下簡單的內存FIFO字符設備驅動,並簡述該驅動的驗證方法。

驅動軟件工程師筆試題

1、寫一段 C 代碼讓程序跳轉到地址是 0x8000 0000 的位置執行

答:((void()(void))0x100000)();或者((void(*)(void))0x100000)();

2、簡述static 關鍵字的作用。

答:1)在函數體內,static 變量的作用範圍爲該函數體,不同於auto 變量,該變量的內存只被分配一次,因此其值在下次調用時仍維持上次的值。

2)在模塊內的static 全部變量可以被模塊內所有函數訪問,但不能被模塊外其他函數訪問。

3)在模塊內的static 函數只可被這一模塊內的其他函數調用,這個函數的使用範圍被限制在聲明它的模塊內。

3、簡要敘述進程和線程這兩個概念。

答:進程是指一個程序在一個數據集合上的一次運行過程。

線程是進程中的一個實體,是被系統獨立調度和執行的基本單位。

進程是程序的一次執行。線程可以理解爲進程中執行的一段程序片段。

4、請簡述自旋鎖和信號量兩個概念並對他們作出比較。

答:1)自旋鎖
自旋鎖是專爲防止多處理器併發而引入的一種鎖,它在內核中大量應用於中斷處理等部分(對於單處理器來說,防止中斷處理中的併發可簡單採用關閉中斷的方式,不需要自旋鎖)。
自旋鎖最多隻能被一個內核任務持有,如果一個內核任務試圖請求一個已被爭用(已經被持有)的自旋鎖,那麼這個任務就會一直進行忙循環——旋轉——等待鎖重新可用。要是鎖未被爭用,請求它的內核任務便能立刻得到它並且繼續進行。自旋鎖可以在任何時刻防止多於一個的內核任務同時進入臨界區,因此這種鎖可有效地避免多處理器上併發運行的內核任務競爭共享資源。
事實上,自旋鎖的初衷就是:在短期間內進行輕量級的鎖定。一個被爭用的自旋鎖使得請求它的線程在等待鎖重新可用的期間進行自旋(特別浪費處理器時間),所以自旋鎖不應該被持有時間過長。如果需要長時間鎖定的話, 最好使用信號量。
自旋鎖的基本形式如下:
spin_lock(&mr_lock);
//臨界區
spin_unlock(&mr_lock);
因爲自旋鎖在同一時刻只能被最多一個內核任務持有,所以一個時刻只有一個線程允許存在於臨界區中。這點很好地滿足了對稱多處理機器需要的鎖定服務。在單處理器上,自旋鎖僅僅當作一個設置內核搶佔的開關。如果內核搶佔也不存在,那麼自旋鎖會在編譯時被完全剔除出內核。
簡單的說,自旋鎖在內核中主要用來防止多處理器中併發訪問臨界區,防止內核搶佔造成的競爭。另外自旋鎖不允許任務睡眠(持有自旋鎖的任務睡眠會造成自死鎖——因爲睡眠有可能造成持有鎖的內核任務被重新調度,而再次申請自己已持有的鎖),它能夠在中斷上下文中使用。
死鎖:假設有一個或多個內核任務和一個或多個資源,每個內核都在等待其中的一個資源,但所有的資源都已經被佔用了。這便會發生所有內核任務都在相互等待,但它們永遠不會釋放已經佔有的資源,於是任何內核任務都無法獲得所需要的資源,無法繼續運行,這便意味着死鎖發生了。自死瑣是說自己佔有了某個資源,然後自己又申請自己已佔有的資源,顯然不可能再獲得該資源,因此就自縛手腳了。

2)信號量
Linux中的信號量是一種睡眠鎖。如果有一個任務試圖獲得一個已被持有的信號量時,信號量會將其推入等待隊列,然後讓其睡眠。這時處理器獲得自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而便可以獲得這個信號量。
信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的情況;只能在進程上下文中使用,因爲中斷上下文中是不能被調度的;另外當代碼持有信號量時,不可以再持有自旋鎖。
信號量基本使用形式爲:
static DECLARE_MUTEX(mr_sem);//聲明互斥信號量
if(down_interruptible(&mr_sem))
//可被中斷的睡眠,當信號來到,睡眠的任務被喚醒
//臨界區
up(&mr_sem);

3)信號量和自旋鎖區別
雖然聽起來兩者之間的使用條件複雜,其實在實際使用中信號量和自旋鎖並不易混淆。注意以下原則:
如果代碼需要睡眠——這往往是發生在和用戶空間同步時——使用信號量是唯一的選擇。由於不受睡眠的限制,使用信號量通常來說更加簡單一些。如果需要在自旋鎖和信號量中作選擇,應該取決於鎖被持有的時間長短。理想情況是所有的鎖都應該儘可能短的被持有,但是如果鎖的持有時間較長的話,使用信號量是更好的選擇。另外,信號量不同於自旋鎖,它不會關閉內核搶佔,所以持有信號量的代碼可以被搶佔。這意味者信號量不會對影響調度反應時間帶來負面影響。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章