一、字符型驅動設備你是怎麼建立設備文件的,就是/dev/下面的設備文件,供上層應用程序打開使用的文件?css
答:mknod命令結合設備的主設備號和次設備號,可建立一個設備文件。
html
評:這只是其中一種方式,也叫手動建立設備文件。還有UDEV/MDEV自動建立設備文件的方式,UDEV/MDEV是運行在用戶態的程序,能夠動態管理設備文件,包括建立和刪除設備文件,運行在用戶態意味着系統要運行以後。那麼在系統啓動期間還有devfs建立了設備文件。一共有三種方式能夠建立設備文件。linux
二、寫一箇中斷服務須要注意哪些?若是中斷產生以後要作比較多的事情你是怎麼作的?
答:中斷處理例程應該儘可能短,把能放在後半段(tasklet,等待隊列等)的任務儘可能放在後半段。
評:寫一箇中斷服務程序要注意快進快出,在中斷服務程序裏面儘可能快速採集信息,包括硬件信息,而後推出中斷,要作其它事情能夠使用工做隊列或者tasklet方式。也就是中斷上半部和下半部。
第二:中斷服務程序中不能有阻塞操做。爲何?你們能夠討論。
android
第三:中斷服務程序注意返回值,要用操做系統定義的宏作爲返回值,而不是本身定義的OK,FAIL之類的。程序員
三、自旋鎖和信號量在互斥使用時須要注意哪些?在中斷服務程序裏面的互斥是使用自旋鎖仍是信號量?仍是二者都能用?爲何?
答:使用自旋鎖的進程不能睡眠,使用信號量的進程能夠睡眠。中斷服務例程中的互斥使用的是自旋鎖,緣由是在中斷處理例程中,硬中斷是關閉的,這樣會丟失可能到來的中斷。
四、原子操做你怎麼理解?爲了實現一個互斥,本身定義一個變量做爲標記來做爲一個資源只有一個使用者行不行?
答:原子操做指的是沒法被打斷的操做。我沒懂第二句是什麼意思,本身定義一個變量怎麼可能標記資源的使用狀況?其餘進程又看不見這個變量
評:第二句話的意思是:
定義一個變量,好比 int flag =0;
if(flag == 0)
{
flag = 1;
操做臨界區;
flag = 0;
面試
}這樣能否?shell
五、insmod 一個驅動模塊,會執行模塊中的哪一個函數?rmmod呢?這兩個函數在設計上要注意哪些?遇到過卸載驅動出現異常沒?是什麼問題引發的?
答:insmod調用init函數,rmmod調用exit函數。這兩個函數在設計時要注意什麼?卸載模塊時曾出現卸載失敗的情形,緣由是存在進程正在使用模塊,檢查代碼後發現產生了死鎖的問題。
編程
評:要注意在init函數中申請的資源在exit函數中要釋放,包括存儲,ioremap,定時器,工做隊列等等。也就是一個模塊註冊進內核,退出內核時要清理所帶來的影響,帶走一切不留下一點痕跡。數組
六、在驅動調試過程當中遇到過oops沒?你是怎麼處理的?緩存
七、ioctl和unlock_ioctl有什麼區別?
八、驅動中操做物理絕對地址爲何要先ioremap?
答:由於內核沒有辦法直接訪問物理內存地址,必須先經過ioremap得到對應的虛擬地址。
九、設備驅動模型三個重要成員是?platfoem總線的匹配規則是?在具體應用上要不要先註冊驅動再註冊設備?有前後順序沒?
十、linux中內核空間及用戶空間的區別?用戶空間與內核通訊方式有哪些?
十一、linux中內存劃分及如何使用?虛擬地址及物理地址的概念及彼此之間的轉化,高端內存概念?
十二、linux中中斷的實現機制,tasklet與workqueue的區別及底層實現區別?爲何要區分上半部和下半部?
1三、linux中斷的響應執行流程?中斷的申請及什麼時候執行(什麼時候執行中斷處理函數)?
1四、linux中的同步機制?spinlock與信號量的區別?
1五、linux中RCU原理?
1六、linux中軟中斷的實現原理?
1七、linux系統實現原子操做有哪些方法?
1八、MIPS Cpu中空間地址是怎麼劃分的?如在uboot中如何操做設備的特定的寄存器?
1九、linux中系統調用過程?如:應用程序中read()在linux中執行過程即從用戶空間到內核空間?
20、linux內核的啓動過程(源代碼級)?
2一、linux調度原理?
2二、linux網絡子系統的認識?
2三、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)都具備緩衝機制。
4一、請編寫一個標準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,寄存器的0~15位有效,請寫出給外設寄存器高八位(8~`15位)設置成0xc3的代碼
50.如何編寫一個LINUX驅動?
提示:主要說字符設備的編寫過程
51.簡述LINUX驅動中字符設備和塊設備的區別?
52.試總結單片機底層開發與LINUX驅動開發有哪些異同?
53.請從網卡、USB HOST、LCD驅動器、NAND FLASH、WIFI 、音頻芯片中選擇一個或者2個(能夠以具體的芯片爲例),對下面的問題作答:
1)若是是外部擴展芯片,請說出你用的芯片的型號
2)畫出上題中你選定相應硬件模塊與CPU的主要引腳連線
3) 編寫上題中你選定相應硬件模塊相應LINUX驅動的流程?
5四、linux驅動分類
Linux設備驅動的分類
(1)字符設備。
(2) 塊設備。
(3) 網絡設備。
字符設備指那些必須以串行順序依次進行訪問的設備,如觸摸屏、磁帶驅動器、鼠標等。塊設備能夠用任意順序進行訪問,以塊爲單位進行操做,如硬盤、軟驅等。字符設備不通過系統的快速緩衝,而塊設備通過系統的快速緩衝。可是,字符設備和塊設備並無明顯的界限,如對於Flash設備,符合塊設備的特色,可是咱們仍然能夠把它做爲一個字符設備來訪問。網絡設備在Linux裏作專門的處理。Linux的網絡系統主要是基於BSD unix的socket 機制。在系統和驅動程序之間定義有專門的數據結構(sk_buff)進行數據的傳遞。系統裏支持對發送數據和接收數據的緩存,提供流量控制機制,提供對多協議的支持。
5五、信號量與自旋鎖
自旋鎖
自旋鎖是專爲防止多處理器併發而引入的一種鎖,它應用於中斷處理等部分。對於單處理器來講,防止中斷處理中的併發可簡單採用關閉中斷的方式,不須要自旋鎖。
自旋鎖最多隻能被一個內核任務持有,若是一個內核任務試圖請求一個已被爭用(已經被持有)的自旋鎖,那麼這個任務就會一直進行忙循環——旋轉——等待鎖從新可用。要是鎖未被爭用,請求它的內核任務便能馬上獲得它而且繼續進行。自旋鎖能夠在任什麼時候刻防止多於一個的內核任務同時進入臨界區,所以這種鎖可有效地避免多處理器上併發運行的內核任務競爭共享資源。
事實上,自旋鎖的初衷就是:在短時間間內進行輕量級的鎖定。一個被爭用的自旋鎖使得請求它的線程在等待鎖從新可用的期間進行自旋(特別浪費處理器時間),因此自旋鎖不該該被持有時間過長。若是須要長時間鎖定的話, 最好使用信號量。可是自旋鎖節省了上下文切換的開銷。
自旋鎖的基本形式以下:
spin_lock(&mr_lock);
//臨界區
spin_unlock(&mr_lock);
由於自旋鎖在同一時刻只能被最多一個內核任務持有,因此一個時刻只有一個線程容許存在於臨界區中。這點很好地知足了對稱多處理機器須要的鎖定服務。在單處理器上,自旋鎖僅僅看成一個設置內核搶佔的開關。若是內核搶佔也不存在,那麼自旋鎖會在編譯時被徹底剔除出內核。
簡單的說,自旋鎖在內核中主要用來防止多處理器中併發訪問臨界區,防止內核搶佔形成的競爭。另外自旋鎖不容許任務睡眠(持有自旋鎖的任務睡眠會形成自死鎖——由於睡眠有可能形成持有鎖的內核任務被從新調度,而再次申請本身已持有的鎖),它可以在中斷上下文中使用。
死鎖:假設有一個或多個內核任務和一個或多個資源,每一個內核都在等待其中的一個資源,但全部的資源都已經被佔用了。這便會發生全部內核任務都在相互等待,但它們永遠不會釋放已經佔有的資源,因而任何內核任務都沒法得到所須要的資源,沒法繼續運行,這便意味着死鎖發生了。自死瑣是說本身佔有了某個資源,而後本身又申請本身已佔有的資源,顯然不可能再得到該資源,所以就自縛手腳了。遞歸使用一個自旋鎖就會出現這種狀況。
信號量
信號量是一種睡眠鎖。若是有一個任務試圖得到一個已被持有的信號量時,信號量會將其推入等待隊列,而後讓其睡眠。這時處理器得到自由去執行其它代碼。當持有信號量的進程將信號量釋放後,在等待隊列中的一個任務將被喚醒,從而即可以得到這個信號量。
信號量的睡眠特性,使得信號量適用於鎖會被長時間持有的狀況;只能在進程上下文中使用,由於中斷上下文中是不能被調度的;另外當代碼持有信號量時,不能夠再持有自旋鎖。
信號量基本使用形式爲:
static DECLARE_MUTEX(mr_sem);//聲明互斥信號量
if(down_interruptible(&mr_sem))
//可被中斷的睡眠,當信號來到,睡眠的任務被喚醒
//臨界區
up(&mr_sem);
信號量和自旋鎖區別
從嚴格意義上講,信號量和自旋鎖屬於不一樣層次的互斥手段,前者的實現有賴於後者。
注意如下原則:
若是代碼須要睡眠——這每每是發生在和用戶空間同步時——使用信號量是惟一的選擇。因爲不受睡眠的限制,使用信號量一般來講更加簡單一些。若是須要在自旋鎖和信號量中做選擇,應該取決於鎖被持有的時間長短。理想狀況是全部的鎖都應該儘量短的被持有,可是若是鎖的持有時間較長的話,使用信號量是更好的選擇。另外,信號量不一樣於自旋鎖,它不會關閉內核搶佔,因此持有信號量的代碼能夠被搶佔。這意味者信號量不會對影響調度反應時間帶來負面影響。
自旋鎖對信號量
需求 建議的加鎖方法
低開銷加鎖 優先使用自旋鎖
短時間鎖定 優先使用自旋鎖
長期加鎖 優先使用信號量
中斷上下文中加鎖 使用自旋鎖
持有鎖是須要睡眠、調度 使用信號量
5六、platform總線設備及總線設備如何編寫
5七、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要慢
5八、module_init的級別
5九、添加驅動
靜態加載和動態加載:
靜態加載是系統啓動的時候由內核自動加載的,這個要事先將驅動編譯進內核才行;
動態加載,也就是模塊加載方式,這種方式下驅動以模塊的形式存放在文件系統中,須要時動態載入內核,這種主要用在調試的時候,比較方便靈活。insmod module.ko
60、IIC原理,總線框架,設備編寫方法,i2c_msg
6一、kernel panic
6二、USB總線,USB傳輸種類,urb等
USB總線:
USB總線屬於一種輪詢式總線,主機控制端口初始化全部的數據傳輸。每一總線動做最多傳送三個數據包,包括令牌(Token)、數據(Data)、聯絡(HandShake)。按照傳輸前制定好的原則,在每次傳送開始時,主機送一個描述傳輸動做的種類、方向、USB設備地址和終端號的USB數據包,這個數據包一般被稱爲令牌包(TokenPacket)。USB設備從解碼後的數據包的適當位置取出屬於本身的數據。數據傳輸方向不是從主機到設備就是從設備到主機。在傳輸開始時,由標誌包來標誌數據的傳輸方向,而後發送端開始發送包含信息的數據包或代表沒有數據傳送。接收端也要相應發送一個握手的數據包代表是否傳送成功。發送端和接收端之間的USB數據傳輸,在主機和設備的端口之間,可視爲一個通道。USB中有一個特殊的通道一缺省控制通道,它屬於消息通道,設備一啓動即存在,從而爲設備的設置、狀態查詢和輸入控制信息提供一個入口。
USB總線的四種傳輸類型:
一、中斷傳輸:由OUT事務和IN事務構成,用於鍵盤、鼠標等HID設備的數據傳輸中 二、批量傳輸:由OUT事務和IN事務構成,用於大容量數據傳輸,沒有固定的傳輸速率,也不佔用帶寬,當總線忙時,USB會優先進行其餘類型的數據傳輸,而暫時中止批量轉輸。 三、同步傳輸:由OUT事務和IN事務構成,有兩個特別地方,第一,在同步傳輸的IN和OUT事務中是沒有返回包階段的;第二,在數據包階段任何的數據包都爲DATA0 四、控制傳輸:最重要的也是最複雜的傳輸,控制傳輸由三個階段構成(初始配置階段、可選數據階段、狀態信息步驟),每個階段可以當作一個的傳輸,也就是說控制傳輸實際上是由三個傳輸構成的,用來於USB設備初次加接到主機以後,主機經過控制傳輸來交換信息,設備地址和讀取設備的描述符,使得主機識別設備,並安裝相應的驅動程式,這是每個USB研發者都要關心的問題。
URB:
USB請求塊(USB request block,urb)是USB設備驅動中用來描述與USB設備通訊所用的基本載體和核心數據結構,很是相似於網絡設備驅動中的sk_buff結構體,是USB主機與設備通訊的「電波」。
6三、同步和互斥
同步和互斥
相交進程之間的關係主要有兩種,同步與互斥。所謂互斥,是指散步在不一樣進程之間的若干程序片段,當某個進程運行其中一個程序片斷時,其它進程就不能運行它們之中的任一程序片斷,只能等到該進程運行完這個程序片斷後才能夠運行。所謂同步,是指散步在不一樣進程之間的若干程序片段,它們的運行必須嚴格按照規定的某種前後次序來運行,這種前後次序依賴於要完成的特定的任務。
顯然,同步是一種更爲複雜的互斥,而互斥是一種特殊的同步。也就是說互斥是兩個線程之間不能夠同時運行,他們會相互排斥,必須等待一個線程運行完畢,另外一個才能運行,而同步也是不能同時運行,但他是必需要安照某種次序來運行相應的線程(也是一種互斥)!
總結:
互斥:是指某一資源同時只容許一個訪問者對其進行訪問,具備惟一性和排它性。但互斥沒法限制訪問者對資源的訪問順序,即訪問是無序的。
同步:是指在互斥的基礎上(大多數狀況),經過其它機制實現訪問者對資源的有序訪問。在大多數狀況下,同步已經實現了互斥,特別是全部寫入資源的狀況一定是互斥的。少數狀況是指能夠容許多個訪問者同時訪問資源
6四、 Linux設備中字符設備與塊設備有什麼主要的區別?請分別列舉一些實際的設備說出它們是屬於哪一類設備。
答:字符設備:字符設備是個可以像字節流(相似文件)同樣被訪問的設備,由字符設備驅動程序來實現這種特性。字符設備驅動程序一般至少實現open,close,read和write系統調用。字符終端、串口、鼠標、鍵盤、攝像頭、聲卡和顯卡等就是典型的字符設備。
塊設備:和字符設備相似,塊設備也是經過/dev目錄下的文件系統節點來訪問。塊設備上可以容納文件系統,如:u盤,SD卡,磁盤等。
字符設備和塊設備的區別僅僅在於內核內部管理數據的方式,也就是內核及驅動程序之間的軟件接口,而這些不一樣對用戶來說是透明的。在內核中,和字符驅動程序相比,塊驅動程序具備徹底不一樣的接口
6五、查看驅動模塊中打印信息應該使用什麼命令?如何查看內核中已有的字符設備的信息?如何查看正在使用的有哪些中斷號?
答:1) 查看驅動模塊中打印信息的命令:dmesg
2) 查看字符設備信息能夠用lsmod 和modprobe,lsmod能夠查看模塊的依賴關係,modprobe在加載模塊時會加載其餘依賴的模塊。
3)顯示當前使用的中斷號cat /proc/interrupt
6六、Linux中引入模塊機制有什麼好處?
答:首先,模塊是預先註冊本身以便服務於未來的某個請求,而後他的初始化函數就當即結束。換句話說,模塊初始化函數的任務就是爲之後調用函數預先做準備。
好處:
1) 應用程序在退出時,能夠無論資源的釋放或者其餘的清除工做,可是模塊的退出函數卻必須仔細此撤銷初始化函數所做的一切。
2) 該機制有助於縮短模塊的開發週期。即:註冊和卸載都很靈活方便。
6七、copy_to_user()和copy_from_user()主要用於實現什麼功能?通常用於file_operations結構的哪些函數裏面?
答:因爲內核空間和用戶空間是不能互相訪問的,若是須要訪問就必須藉助內核函數進行數據讀寫。copy_to_user():完成內核空間到用戶空間的複製,copy_from_user():是完成用戶空間到內核空間的複製。通常用於file_operations結構裏的read,write,ioctl等內存數據交換做用的函數。固然,若是ioctl沒有用到內存數據複製,那麼就不會用到這兩個函數。
6八、請簡述主設備號和次設備號的用途。若是執行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結構。
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);
釋放中斷和中斷信號線
7一、中斷和輪詢哪一個效率高?怎樣決定是採用中斷方式仍是採用輪詢方式去實現驅動?
答:中斷是CPU處於被中狀態下來接受設備的信號,而輪詢是CPU主動去查詢該設備是否有請求。凡事都是兩面性,因此,看效率不能簡單的說那個效率高。若是是請求設備是一個頻繁請求cpu的設備,或者有大量數據請求的網絡設備,那麼輪詢的效率是比中斷高。若是是通常設備,而且該設備請求cpu的頻率比較底,則用中斷效率要高一些。
7二、簡單描述在cs8900的驅動設計中, 發送數據frame和接收數據frame的過程。
答:1)發送流程以下:
(1) 網絡設備驅動程序從上層協議傳遞過來的sk_buff參數得到數據包的有效數據和長度,將有效數據放入臨時緩衝區。
(2) 對於以太網,若是有效數據的長度小於以太網衝突檢測所要求的數據楨的最小長度,則給臨時緩衝區的末尾填充0
(3) 設置硬件寄存器,驅使網絡設備進行數據發送操做。
2)接收流程
網絡設備接收數據主要是由中斷引起設備的中斷處理函數,中斷處理函數判斷中斷類型,若是爲接收中斷,則讀取接受到的數據,分配sk_buff數據結構和數據緩衝區,將接收到的數據複製到數據緩衝區,並調用netif_rx()函數將sk_buff傳遞給上層協議。
7三、cs8900.c的驅動中,發送數據frame的過程爲何須要關中斷?接收數據frame的過程爲何不須要關中斷?
答:在發送過程當中是不能被打斷的,在發送的過程當中,不關中斷,這時候若是有一箇中斷到來,那麼cpu有可能會去相應該中斷,若是該中斷須要改寫的數據是發送數據的緩衝區,那麼緩衝區將被改寫,這樣即便cpu相應完畢該中斷,再發送數據,接收方也不認識該數據不能接收。
在接收數據的時候,須要打開中斷,是由於要及時的相應接收到的數據。若是關閉該中斷,那麼接收方有可能由於相應優先級高的中斷而接收不到該數據。
7四、簡單描述skbuff這個數據結構在網絡結構中所起到的做用,爲何須要一個skbuff,它的分配和釋放主要都在什麼部位
答:sk_buff結構很是重要,它的含義爲「套接字緩衝區」,用於在linux網絡子系統中的各層之間傳遞數據。
當發送數據包時,linux內核的網絡處理模塊必須創建一個包含要傳輸的數據包的sk_buff,而後將sk_buff遞交給下層,各層在sk_buff中添加不一樣的協議頭直至交給網絡設備發送。一樣的,當網絡設備從網絡媒介上接受到數據包後,它必須將接受到的數據轉換爲sk_buff數據結構並傳遞給上層,蓋層不拋去相應的協議頭直至交給用戶。分配sk_buff在接收一開始就應該分配,在發送完畢數據以後能夠釋放sk_buff。
[預處理器(Preprocessor)]
1. 用預處理指令#define 聲明一個常數,用以代表1年中有多少秒(忽略閏年問題)
#define SECONDS_PER_YEAR (60 * 60 * 24 *365)UL
我在這想看到幾件事情:
1). #define 語法的基本知識(例如:不能以分號結束,括號的使用,等等)
2). 懂得預處理器將爲你計算常數表達式的值,所以,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。
3). 意識到這個表達式將使一個16位機的整型數溢出-所以要用到長整型符號L,告訴編譯器這個常數是的長整型數。
4). 若是你在你的表達式中用到UL(表示無符號長整型),那麼你有了一個好的起點。記住,第一印象很重要。
2. 寫一個「標準」宏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);
3. 預處理器標識#error的目的是什麼?
中止編譯並顯示出錯誤信息
[死循環(Infinite loops)]
4. 嵌入式系統中常常要用到無限循環,你怎麼樣用C編寫死循環呢?
這個問題用幾個解決方案。我首選的方案是:
while(1) { }
一些程序員更喜歡以下方案:
for(;;) { }
這個實現方式讓我爲難,由於這個語法沒有確切表達到底怎麼回事。若是一個應試者給出這個做爲方案,我將用這個做爲一個機會去探究他們這樣作的
基本原理。若是他們的基本答案是:「我被教着這樣作,但從沒有想到過爲何。」這會給我留下一個壞印象。
第三個方案是用 goto
Loop:
…
goto Loop;
應試者如給出上面的方案,這說明或者他是一個彙編語言程序員(這也許是好事)或者他是一個想進入新領域的BASIC/FORTRAN程序員。
[數據聲明(Data declarations)]
5. 用變量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]
6. 關鍵字static的做用是什麼?
這個簡單的問題不多有人能回答徹底。在C語言中,關鍵字static有三個明顯的做用:
1). 在函數體,一個被聲明爲靜態的變量在這一函數被調用過程當中只會初始化一次。
2). 在模塊內(但在函數體外),一個被聲明爲靜態的變量能夠被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。
3). 在模塊內,一個被聲明爲靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地範圍內使用。
大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是不多的人能懂得第三部分。這是一個應試者的嚴重的缺點,由於他顯然不懂得本地化數據和代碼範圍的好處和重要性。
linux驅動面試題2
general purpose input/output
GPIO是相對於芯片自己而言的,如某個管腳是芯片的GPIO腳,則該腳可做爲輸入或輸出高或低電平使用,固然某個腳具備複用的功能,便可作GPIO也可作其餘用途。
也就是說你能夠把這些引腳拿來用做任何通常用途的輸入輸出,例如用一根引腳連到led的一極來控制它的亮滅,也能夠用一根(一些)引腳連到一個傳感器上以得到該傳感器的狀態,這給cpu提供了一個方便的控制周邊設備的途經。若是沒有足夠多的gpio管腳,在控制一些外圍設備時就會力有不逮,這時可採起的方案是使用CPLD來幫助管理。
電容技術觸摸屏利用人體的電流感應進行工做 。用戶觸摸屏幕時 ,因爲人體電場,用戶和觸摸屏表面造成以一個耦合電容, 對於高頻電流來講,電容是直接導體,因而手指從接觸點吸走一個很小的電流
搞的比較複雜。主要思想就是a-b的值的最高位是否爲0;可是又得考慮整數溢出的問題,因此很複雜。不知道哪位大俠有更好的辦法,指點指點。
一、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)都具備緩衝機制。
二、請編寫一個標準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,寄存器的0~15位有效,請寫出給外設寄存器高八位(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裏面自己存放的只是一個地址,難道是這兩個地址有不一樣麼?
4. 中斷的上半部分和下半部分的問題:
講下分紅上半部分和下半部分的緣由,爲什麼要分?講下如何實現?
5. 內核函數mmap的實現原理,機制?
6. 驅動裏面爲何要有併發、互斥的控制?如何實現?講個例子?
7. spinlock自旋鎖是如何實現的?
8. 任務調度的機制?
【2、本人碰到】
1. 嵌入式linux和wince操做系統的特色和特性?
2. 嵌入式linux中tty設備驅動的體系結構?
3. 嵌入式設備,爲加快啓動速度,能夠作哪些方面的優化?
4. USB設備的枚舉過程?
5. PSRAM、SDRAM、DDR、DDR2的時序特性?
6. I2C觸摸屏芯片與CPU的數據傳輸流程?畫出相關圖例?(這題目記得不是太清楚了,大概是考查I2C設備驅動的數據傳輸過程)
一、linux驅動分類
二、信號量與自旋鎖
三、platform總線設備及總線設備如何編寫
四、kmalloc和vmalloc的區別
五、module_init的級別
六、添加驅動
七、IIC原理,總線框架,設備編寫方法,i2c_msg
八、kernel panic
九、USB總線,USB傳輸種類,urb等
十、android boot 流程
十一、android init解析init.rc
1、選擇題
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:下列語句定義整型指針p一、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.以上均不是
2、簡答題
八、下面的程序或程序段存在一個錯誤或不妥處請在其下劃一條線,並將改正的內容寫到每小題後的空白處
main()
{ char cl,c2;
cl='9';
c2='10';
printf(」cl=%c,c2=%c\n」,c1,c2);
}
九、下面的代碼輸出是什麼,爲何?
void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
十、中斷是嵌入式系統中重要的組成部分,這致使了不少編譯開發商提供一種擴展 ―讓標準 C支持中斷。具表明事實是,產生了一個新的關鍵字__interrupt,下面的代碼就使用了 __interrupt關鍵字去定義了一箇中斷服務子程序 (ISR),請評論一下這段代碼,找出錯誤並改正.
__interruptdouble compute_area (double radius)
{
doublearea = PI * radius * radius;
printf("\nArea= %f", area);
returnarea;
}
3、內核驅動題
十一、請簡述arm linux內核啓動流程。
十二、驅動裏面爲何要有併發、互斥的控制?如何實現?舉例說明。
1三、請簡述linux內核終端處理分紅上半部分和下半部分的緣由,爲什麼要分?如何實現?
4、編程實現題
14、設計並實現一個在linux平臺下簡單的內存FIFO字符設備驅動,並簡述該驅動的驗證方法。
一、寫一段 C 代碼讓程序跳轉到地址是 0x8000 0000 的位置執行
答:(*(void(*)(void))0x100000)();或者((void(*)(void))0x100000)();
二、簡述static 關鍵字的做用。
答:1)在函數體內,static 變量的做用範圍爲該函數體,不一樣於auto 變量,該變量的內存只被分配一次,所以其值在下次調用時仍維持上次的值。
2)在模塊內的static 所有變量能夠被模塊內全部函數訪問,但不能被模塊外其餘函數訪問。
3)在模塊內的static 函數只可被這一模塊內的其餘函數調用,這個函數的使用範圍被限制在聲明它的模塊內。
三、簡要敘述進程和線程這兩個概念。
答:進程是指一個程序在一個數據集合上的一次運行過程。
線程是進程中的一個實體,是被系統獨立調度和執行的基本單位。
進程是程序的一次執行。線程能夠理解爲進程中執行的一段程序片斷。
四、請簡述自旋鎖和信號量兩個概念並對他們做出比較。
答: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)信號量和自旋鎖區別 雖然聽起來二者之間的使用條件複雜,其實在實際使用中信號量和自旋鎖並不易混淆。注意如下原則: 若是代碼須要睡眠——這每每是發生在和用戶空間同步時——使用信號量是惟一的選擇。因爲不受睡眠的限制,使用信號量一般來講更加簡單一些。若是須要在自旋鎖和信號量中做選擇,應該取決於鎖被持有的時間長短。理想狀況是全部的鎖都應該儘量短的被持有,可是若是鎖的持有時間較長的話,使用信號量是更好的選擇。另外,信號量不一樣於自旋鎖,它不會關閉內核搶佔,因此持有信號量的代碼能夠被搶佔。這意味者信號量不會對影響調度反應時間帶來負面影響。