USB開發步驟之軟體篇

來源:互聯網
上載者:User
 

我這裡重點的介紹如何寫驅動程式,對於一些應用程式我就不做介紹了,因為我對於那些高層的東西寫得很少。倘若再講,有班門弄斧之嫌,呵呵!
作為WIN98和WIN2K推薦的一項新技術來說,USB的驅動程式和以往的直接跟硬體打交道的WIN95的VXD的方式的驅動程式不同,它應該是WDM類型的。

USB的WDM介面框圖如下(這個圖可以說是USB軟體總體框圖)

對於HID的裝置,就可以採用左上邊的結構,其它類的話採用右上的結構,其實右邊的結構可以又細分成兩層,一層是Class Driver,一層是Miniport Driver。而倒數第三行的UHCD和OpenHCI分別是由INTEL和COMPAQ兩位老大定的一個和硬體有關的底層驅動程式標準,各位可以根據所需要的選擇。

對於USB的驅動程式,大家還得去瞭解WDM驅動程式的寫法,或者早些時候的NT驅動程式,其實WDM驅動程式可以看做是NT驅動程式的一個update,只是增加了一些新的特性。

“寫驅動程式是一個很漫長和繁瑣的工作,在此之前,你最好要熟悉硬體,熟悉C/C++,還要用過DDK,會用一些偵錯工具,如SOFTICE和WINDBG之類。如果一切就緒,你就可以開始寫驅動程式,工作的進程有時侯會取決於你的運氣”。(這是一位留美的朋友對我說的,我寫出來和大家共用)

下面是我從一個朋友那裡得到的一篇文章的摘要:

NT驅動程式的分層結構
驅動程式是指管理某個外圍裝置的一段程式碼。NT採用更靈活的分層驅動方法,允許雜應用程式和硬體之間 存在幾個驅動程式層次。分層機制允許NT更加廣泛地定義驅動程式,包括檔案系統、邏輯卷管理器和各種網路組件,各種物理裝置驅動程式等等。

1、 裝置驅動程式
這些是管理實際資料轉送和控制特定類型的物理裝置的操作的驅動程式,包括開始和完成I/O操作,處理中斷和執行特定的裝置要求的任何差錯處理。

2、 中間驅動程式
NT允許在物理裝置驅動程式上分層任意數目的中間驅動程式。這些中介層次提供擴充I/O系統的功能一種方法,而不必修改底層的驅動程式。這也是微軟鼓吹的他們的系統靈活的一面!實際上我覺得這樣反而犧牲了一些效率上的東西。

3、 檔案系統驅動程式(FSD)
FSD是一類比較特殊的驅動程式,通常負責維護各種檔案系統 所需要的磁碟結構。注意我們並不能使用DDK來開發FSD,而必須使用Microsoft的檔案系統開發人員工具包。

一般比較少寫中間過濾驅動程式,過濾驅動程式它截獲和修改高層發送給類驅動程式的請求。這樣就允許利用現有類驅動程式的功能,而不必從頭開始寫所有程式。NT核心模式對象在我們的實際開發過程中的對象是裝置,由於連接埠驅動程式已經隱藏了硬體控制操作,因此我在這裡不講述跟硬體相關的部份。如果今後的開發對象不同,需要對硬體進行操作的時候,可能會對中斷、DMA等有比較詳細的瞭解,這些內容可以參考DDK協助。

NT使用對象技術管理所有的資料,下面分別對一般驅動程式所涉及的一些對象做一介紹。不過在介紹這些對象之前,有必要先對驅動程式的結構做一介紹。

 
驅動程式結構
NT驅動程式和一般的DOS/Windows C語言程式不一樣,它沒有main()或者WinMain()函數入口。和DLL類似地,它向作業系統顯露一個名稱為DriverEntry()的函數,在啟動驅動程式的時候,作業系統將調用這個入口。DriverEntry除了做一些必 要的裝置初始化工作外,還初始化一些Dispatch常式入口。我們知道,NT應用和裝置驅動程式打交道主要是通過CreateFile、 ReadFile、WriteFile 和DeviceIoControl等Win32 API來進行 的。這些API其實都對應著驅動程式的一些Dispatch常式。而驅動程式除了DriverEntry以外,主要就是由這些Dispatch例 程組成的。例如調用Win32 API CreateFile的時候,作業系統最終轉化為對驅動程式IRP_MJ_CREATE功能代碼所對應的 Dispatch常式的調用,如果驅動程式沒有提供該常式, CreateFile調用就會失敗。
NT中一些常用的功能代碼和Win32 API的對象關係如下所示。
功能代碼                                                                  說明
IRP_MJ_CREATE                                                 開啟裝置CreateFile
IRP_MJ_CLEANUP                                              在關閉裝置時,取消掛起的I/O請求CloseHandle
IRP_MJ_CLOSE                                                   關閉裝置CloseHandle
IRP_MJ_READ                                                    從裝置獲得資料ReadFile
IRP_MJ_WRITE                                                       向裝置發送資料WriteFile
IRP_MJ_DEVICE_CONTROL                               對使用者模式或核心模式客戶程式可用的控制操作DeviceIoControl
IRP_MJ_INTERNAL_DEVICE_CONTROL            只對核心模式客戶程式可用的控制操作
IRP_MJ_QUERY_INFORMATION                           得到檔案的長度GetFileLength
IRP_MJ_SET_INFORMATION                                 設定檔案的長度SetFileLength
IRP_MJ_FLUSH_BUFFERS                                  寫輸出緩衝區或丟棄輸入緩衝區
FlushFileBuffers
FlushConsoleInputBuffer
PurgeComm
IRP_MJ_SHUTDOWN                                           系統關閉InitialSystemShutdown

和上面的驅動程式支援的功能代碼相對應,一般的驅動程式看起來就象下面的樣子。
DriverEntry(…) // 驅動程式入口
{

DeviceObject->MajorFunction[IRP_MJ_CREATE] = XXDriverCreateClose; //XX對應的是你自己給你的驅動程式的命名
DeviceObject->MajorFunction[IRP_MJ_CLOSE] = XXDriverCreateClose;
DeviceObject->MajorFunction[IRP_MJ_READ] = XXDriverReadWrite;
DeviceObject->MajorFunction[IRP_MJ_WRITE] = XXDriverReadWrite;

}
XXDriverCreateClose(…) // 對應IRP_MJ_CREATE和IRP_MJ_CLOSE的常式
{
//……….
}
XXDriverDeviceControl(…)// 對應IRP_MJ_DEVICE_CONTROL的常式
{
//……….
}
XXDriverReadWrite(…) // 對應IRP_MJ_READ和IRP_MJ_WRITE的常式
{
//……….
}

一個驅動程式並不需要支援所有的功能代碼,比如如果一個驅動程式根本就不必要與使用者模式客戶程式互動,那麼就不用支援IRP_MJ_CREATE和IRP_MJ_CLOSE。又如裝置不支援裝置讀寫,就不用支援IRP_MJ_READ和IRP_MJ_WRITE。 驅動程式對象是在作業系統啟動驅動程式、在調用驅動程式 入口DriverEntry之前就已經建立好了的,並且作為DriverEntry 函數的參數傳遞給驅動程式。如果驅動程式啟動失敗,操作 系統將刪除該對象。該對象的資料結構如下。注意下表並不是完整地列出了ntddk.h中的DEVICE_OBJECT結構體的所有數 據項,這裡僅列出了一般驅動程式可能使用到的資料項目。 

Driver對象資料項目   說明
PDEVICE_OBJECT  DeviceObject   由本驅動程式建立的Device對象的鏈表
ULONG Flags     PDRIVER_INITIALIZE DriverInit     驅動程式初始化常式(一般較少用)
PDRIVER_STARTIO DriverStartIo        StartIo常式入口,一般該常式對低層裝置驅動程式用得較多, 高層驅動程式較少使用本常式。
PDRIVER_UNLOAD  DriverUnload   卸載驅動程式常式,如果想在控制面版的裝置裡停止該裝置,應該提供本常式。
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]     驅動程式的Dispatch常式表

在上面提到過驅動程式是管理同類型的所有裝置,所以上面的 結構中DeviceObject指向的就不是單個的裝置對象,而是一個對象鏈表,這個鏈表的維護在下面介紹Device對象時可以看到。 Device對象與Device Extension 驅動程式在調用IoCreateDevice函數成功後就建立了一個Device 對象。下面對Device對象幾個比較重要的資料做一介紹。

Device對象資料項目       說明
PVOID DeviceExtension   指向Device Extension結構的指標
PDRIVER_OBJECT DriverObject 指向這個裝置的Driver對象的指標,IoCreateDevice會 自動填寫本資料。
ULONG Flags 指定這個裝置的緩衝策略
PDEVICE_OBJECT NextDevice 指向屬於這個驅動程式的下一個裝置對象,依靠本資料來維護裝置對象鏈表
CCHAR StackSize   發送到這個裝置的IRP需要的I/O堆棧單元的最小數目,一般對層次驅動程式來說,本資料應該比其下層裝置的大1
ULONG AlignmentRequirement 緩衝區要求的記憶體對齊,一般對層次驅動程式來說,本值應該 和其下層裝置的對齊一致

Device記錄著裝置的特徵和狀態資訊,對系統上的每個虛擬、邏輯的和物理的裝置都有一個Device對象。例如對一個硬碟驅動程式,對一個物理硬碟有一個名稱為Partition0的Device對象,對應整個物理磁碟,同時對硬碟的每個分區,也都有一個Device對象,它們的名稱分別為PartitionX(X從1開始,每個分區對應一個數字)。
Device Extension是串連到Device對象的一個很重要的資料結構,它的資料結構是由驅動程式設計者自己來確定的,在 調用IoCreateDevice的時候應該指定它的大小,Device Extension其實是由作業系統在非份頁記憶體池中為每個Device 對象分配的一塊記憶體。由於驅動程式必須是完全可重新進入的, 因此使用任何全域變數和靜態變數都不是好的辦法,一般來 說和裝置有關的任何需要保持的資訊都應該放到Device Extension裡去。
裝置的緩衝策略也必須提一下,這裡的Flag的緩衝策略主要 決定裝置讀寫(功能代碼IRP_MJ_READ和IRP_MJ_WRITE)時候的 緩衝策略,另外功能代碼IRP_MJ_DEVICE_CONTROL時候的緩衝 策略是由IOCTL控制碼本身來決定的。兩者不能混為一談。 在下面我將專門用一節來討論I/O的緩衝策略。
I/O請求包(IRP)
在上面的結構裡面已經出現了IRP了,在這裡對它做一說明。 在NT中,幾乎所有的I/O都是包驅動的,可以說驅動程式和作業系統其他部份都是通過I/O請求包來進行互動的。我們 來看看一個I/O請求的執行過程。
(1) 作業系統的I/O管理器從非分頁式記憶體分配一個IRP,響應一個I/O請求。基於由客戶指定的I/O函數,I/O管理器將該 IRP傳遞給合適的驅動程式的Dispatch常式。
(2) Dispatch常式檢查請求的參數是否有效,如果有效,驅動程式根據請求的內容進行一系列的操作。否則設定錯 誤狀態資訊直接返回。
(3) 操作完成時,將資料(如果有)和狀態資訊存放到IRP中 並返回給I/O管理器。
(4) I/O管理器對返回的IRP進行適當的處理後將最後狀態和 資料(如果有)返回給使用者。

一個IRP的主要資料項目如下表所示。
IRP包括一個IRP頭和一個IRP stack 的地區。由於WDM的模式下都是包驅動的,所裡IRP可以說是一個非常重要的東東。還有那個該死的URB(God damn URB!)[人一輩子真的很過癮,有些人或有些事你明明不喜歡或做不來,可是有時侯你又不得不硬著頭皮去做,就像一大堆球迷圍著一堆狗屎般的中國足球,那班傻兒真是要錢不要臉,丟咱中國人的臉]

IRP主要資料項目 說明
IO_STATUS_BLOCK IoStatus 存放I/O請求的狀態
PVOID AssociatedIrp.SystemBuffer 如果裝置執行緩衝I/O,則為指向系統空間緩衝區的指標。 否則為NULL
PMDL MdlAddress 如果裝置執行直接I/O,指向使用者空間緩衝區的記憶體描述表的指標
PVOID UserBuffer I/O緩衝區的使用者空間地址
BOOLEAN Cancel    指示IRP已被取消

關於AssociatedIrp.SystemBuffer、MdlAddress和UserBuffer將在 下面的I/O緩衝區策略裡面更詳細地討論。

NT還有更多其他的對象,例如中斷對象、Controller對象、定時器對象等等,但在我們開發的驅動程式中並沒有用到,因此在這裡不做介紹。
I/O緩衝策略
很明顯的,驅動程式和客戶應用程式經常需要進行資料交換,但我們知道驅動程式和客戶應用程式可能不在同一個地址空間,因此作業系統必須解決兩者之間的資料交換。這就就設計到裝置的I/O緩衝策略。
讀寫請求的I/O緩衝策略
前面說到通過設定Device對象的Flag可以選擇控制處理讀寫請求的I/O緩衝策略。下面對這些緩衝策略分別做一介紹。
1、緩衝I/O(DO_BUFFERED_IO)
在讀寫請求的一開始,I/O管理器檢查使用者緩衝區的可訪問性,然後分配與調用者的緩衝區一樣大的非分頁池,並把它的地址放在IRP的AssociatedIrp.SystemBuffer域中。驅動程式就利用這個域來進行實際資料的傳輸。
對於IRP_MJ_READ讀請求,I/O管理器還把IRP的UserBuffer網域設定 成調用者緩衝區的使用者空間地址。當請求完成時,I/O管理器利用 這個地址將資料從驅動程式的系統空間拷貝回調用者的緩衝區。對 於IRP_MJ_WRITE寫請求,UserBuffer被設定為NULL,並把使用者緩衝 區的資料拷貝到系統緩衝區中。
2、 直接I/O(DO_DIRECT_IO)
I/O管理器首先檢查使用者緩衝區的可訪問性,並在實體記憶體中鎖定它。然後它為該緩衝區建立一個記憶體描述表(MDL),並把MDL的地址 存放在IRP的MdlAddress域中。AssociatedIrp.SystemBuffer和 UserBuffer都被設定為NULL。驅動程式可以調用函數 MmGetSystemAddressForMdl得到使用者緩衝區的系統空間地址,從而 進行資料操作。這個函數將調用者的緩衝區映射到非份頁的地址空 間。驅動程式完成I/O請求後,系統自動從系統空間解除緩衝區的映射。
3、 這兩種方法都不是
這種情況比較少用,因為這需要驅動程式自己來處理緩衝問題。 I/O管理器僅把調用者緩衝區的使用者空間地址放到IRP的UserBuffer 域中。我們並不推薦這種方式。

IOCTL緩衝區的緩衝策略
IOCTL請求涉及來自調用者的輸入緩衝區和返回到調用者的輸出 緩衝區。為了理解IOCTL請求,我們先來看看WIN32 API DeviceIoControl函數的原型。
BOOL DeviceIoControl (
HANDLE hDevice, // 裝置控制代碼
DWORD dwIoControlCode, // IOCTL請求作業碼
LPVOID lpInBuffer, // 輸入緩衝區地址
DWORD nInBufferSize, // 輸入緩衝區大小
LPVOID lpOutBuffer, // 輸出緩衝區地址
DWORD nOutBufferSize, // 輸出緩衝區大小
LPDWORD lpBytesReturned, // 存放返回位元組數的指標
LPOVERLAPPED lpOverlapped // 用於同步操作的Overlapped結構體指標
);
IOCTL請求有四種緩衝策略,下面一一介紹。
1、 輸入輸出緩衝I/O(METHOD_BUFFERED)
I/O管理器首先分配一個非分頁池,它足夠大地存放調用者的輸入或輸出緩衝區(不管哪個更大)。非分頁緩衝區的地址放在IRP的AssociatedIrp.SystemBuffer域中,然後把IOCTL的輸入資料拷貝 到這個非份頁緩衝區中,並把IRP的UserBuffer網域設定成調用者輸出緩衝區的使用者空間地址。當驅動程式完成IOCTL請求時,I/O管理器將這個非份頁緩衝區中的資料拷貝到調用者的輸出緩衝區。注意這裡同一個非份頁池同時用於輸入和輸出緩衝區,因此驅動程式在向緩衝區寫東西之前應該把輸入的所有資料讀出來。
2、 直接輸入緩衝輸出I/O(METHOD_IN_DIRECT)
I/O管理器首先檢查調用者輸入緩衝區的可訪問性,並在實體記憶體中將其鎖定。然後為該輸入緩衝區建立一個MDL,並把指定該MDL的指標存放到IRP的MdlAddress域中。同時,I/O管理器還在非份頁池中分配一輸出緩衝區,並把這個緩衝區的地址存放在IRP的AssociatedIrp.SystemBuffer域中,並把IRP的UserBuffer網域設定成調用者輸出緩衝區的使用者空間地址。當驅動程式完成IOCTL請求時,I/O管理器將非份頁緩衝區中的資料拷貝到調用者的輸出緩衝區。
3、 緩衝輸入直接輸出I/O(METHOD_OUT_DIRECT)
I/O管理器首先檢查調用者輸出緩衝區的可訪問性,並在實體記憶體中將其鎖定。然後為該輸出緩衝區建立一個MDL,並把指定該MDL的指標存放到IRP的MdlAddress域中。同時,I/O管理器還在非份頁池中分配一輸入緩衝區,並把這個緩衝區的地址存放在IRP的AssociatedIrp.SystemBuffer域中, 同時把調用者使用者輸入緩衝區中的資料拷貝到系統緩衝區中,並把IRP的 UserBuffer網域設定為NULL。
4、 上面三種方法都不是(METHOD_NEITHER)
I/O管理器把調用者的輸入緩衝區的地址放到IRP當前I/O堆棧單元的Parameters.Devi ceIoControl.TypeInputBuffer域中,把輸出緩衝 區的地址存放到IRP的UserBuffer域中。這兩個地址都是使用者空間地 址。
從上面的說明可以看出,在執行緩衝I/O時,I/O管理器將在非份頁池 中分配記憶體,如果調用者的緩衝區比較大時,分配的非份頁池也將 比較大。非份頁池是系統比較寶貴的資源,因此,如果調用者的緩 沖區比較大時,我們一般採用直接I/O的方式(例如磁碟讀寫請求等), 這樣不僅節省系統資源,另一方面由於省去了I/O管理器在系統緩衝 區和調用者緩衝區之間的資料拷貝,也提高了效率,這對存在大量 資料傳送的驅動程式尤其明顯。
可以注意到DDK中的Samples下,幾乎所有的常式的讀寫請求都是直 接I/O的,而對於IOCTL請求則是緩衝區I/O的居多。

開始驅動程式設計
下面的文字是從Microsoft的DDK協助中節選出來的,它讓我們明 白在開始設計驅動程式應該注意些什麼問題,這些都是具有普遍 意義的開發準則。應該支援哪些I/O請求在開始寫任何代碼之前, 應該首先確定我們的驅動程式應該處理哪些IRP常式。
如果你在設計一個裝置驅動程式,你應該支援和其他相同類型 裝置的NT驅動程式相同的IRP_MJ_XXX和IOCTL請求代碼。
如果你是在設計一個中介層NT驅動程式,應該首先確認你下層 驅動程式所管理的裝置,因為一個高層的驅動程式必須具有低層 驅動程式絕大多數IRP_MJ_XXX常式入口。高層驅動程式在接到I/O 請求時,在確定自身IRP當前堆棧單元參數有效前提下 ,設定好IRP中下一個低層驅動程式的堆棧單元,然後再調用IoCallDriver 將請求傳遞給下層驅動程式處理。
一旦決定好了你的驅動程式應該處理哪些IRP_MJ_XXX,就可以開始 確定驅動程式應該有多少個Dispatch常式。當然也可以考慮把某些 RP_MJ_XXX處理的常式合并為同一常式處理。例如在ChangerDisk和 VDisk裡,對IRP_MJ_CREATE和IRP_MJ_CLOSE處理的常式就是同一函數。 對IRP_MJ_READ和IRP_MJ_WRITE處理的常式也是同一個函數。
應該有多少個Device對象?
一個驅動程式必須為它所管理的每個可能成為I/O請求的目標的物理和邏輯裝置建立一個命名Device對象。一些低層的驅動程式還可能要建立一些不確定數目的Device對象。例如一個硬碟驅動程式必須為每一個物理硬碟建立一個Device對象,同時還必須為每個物理磁碟上的每個邏輯分區建立一個Device對象。
一個高層驅動驅動程式必須為它所代表的虛擬設備建立一個Device 對象,這樣更高層的驅動程式才能串連它們的Device對象到這個驅動程式的Device對象。另外,一個高層驅動程式通常為它低層驅動 程式所建立的Device對象建立一系列的虛擬或邏輯Device對象。
儘管你可以分階段來設計你的驅動程式,因此一個處在開發階段的 驅動程式不必一開始就建立出所有它將要處理的所有Device對象。 但從一開始就確定好你最終要建立的所有Device對象將有助於設計者所要解決的任何同步問題。另外,確定所要建立的Device對象還有助於你定義Device對象的Device Extension的內容和資料結構。
開始驅動程式開發
驅動程式的開發是一個從粗到細逐步求精的過程。NT DDK的src/ 目錄下有一個龐大的樣板代碼,幾乎覆蓋了所有類型的裝置驅動程式、高層驅動程式和過濾器驅動程式。在開始開發你的驅動程式之前,你應該在這個樣板庫下面尋找是否有和你所要開發的類似類型的常式。例如我們所開發的驅動程式,雖然DDK對USB描述得不是很詳細,我們還是可以在src/storage/class目錄發現很多和USB裝置有關的驅動程式。下面我們來看開發驅動程式的基本步驟。
最簡的驅動程式架構
1、 寫一個DriverEntry常式,在裡面調用IoCreateDevice建立 一個Device對象。
2、 寫一個處理IRP_MJ_CREATE請求的Dispatch常式的基本架構 (參見DDK Kernel-Mode Drivers 4.4.3描述的一個DispatchCreate 常式所要完成的最基本工作。當然寫了DispatchCreate常式後, 要在DriverEntry常式為IRP_MJ_CREATE初始化常式入口)。如果驅動程式建立了多於一個Device對象,則必須為IRP_MJ_CLOSE 請求寫一個常式,該常式通常情況下可以和DispatchCreate共用一個常式,參見參見DDK Kernel-Mode Drivers 4.4.3。
3、 編譯串連你的驅動程式。
用下面的方法來測試你的驅動程式。
首先按上面介紹的方法安裝好驅動程式。
其次我們還得為NT邏輯裝置名稱和目標Device對象名稱之間建立 起符號串連,我們在前面已經知道Device對象名稱對WIN32使用者模式 是不可見的,是不能直接通過API來訪問的,WIN 32 API只能訪問NT 邏輯裝置名稱。我們可以通過修改註冊表來建立這兩種名稱之間的符 號串連。運行REGEDT32.EXE在/HKEY_LOCAL_MACHINE/ System/ CurrentControlSet/Control/ Session Manager/ DOS Devices下建立起符號串連(這種符號串連也可以在驅動程式裡調用函數 IoCreateSymbolicLink來建立)。
重新啟動系統。
編寫一個簡單的測試程式調用WIN32API CreateFile函數以剛才你命名的NT邏輯裝置名開啟這個裝置。如果開啟成功,那麼你也就成功地寫出了一個最簡單的驅動程式了。
支援更多的裝置I/O請求
例如你的驅動程式可能需要對IRP_MJ_READ請求做出響應(完成後可用WIN32 API ReadFile函數進行測試)。如果你的驅動程式需要能夠手工卸載,那麼還必須對IRP_MJ_CLOSE做出響應。為你所需要處理IRP_MJ_XXX寫好處理常式,並在DriverEntry裡面初始化好這些例 程入口。
一個低層的驅動程式可能需要最起碼一個StartIo,ISR和DpcForIsr 常式,可能需要一個SynchCritSection常式,如果裝置使用了DMA, 那麼可能還需要一個AdapterControl常式。關於這些常式,請參考 DDK相應文檔。
對於高層驅動程式可能需要一個或多個IoCompletion常式,最起碼 完成檢查I/O狀態塊然後調用IoCompleteRequest的工作。 如果需要,還要對Device Extension資料結構和內容做些修改。

驅動程式的書寫過程的確是很煩人的,從你開始理解結構開始,你就像掉在一個泥潭裡一樣,無論你如何出拳,發覺總是稀泥一堆。即使你是電腦高手,可以寫三千行原始碼沒犯一個錯,一次寫完,一次就編譯通過(我的一個“同事”在面試的時候對我們老闆說的,我想他說的對,他沒犯一個錯,而是犯了三十萬零一個半錯,不過,由不的你不信,俺朋友老闆就信世間有這類高手,並供為上賓),你還得瞭解一些基礎的硬體知識,你還要瞭解你的驅動程式的裝置的種類,裝置的硬體結構,一些特殊的寄存器,或許一些更基礎的組譯工具你也的去跑一遍。還的去看什麼微微有點軟出的什麼鳥DDK(這玩意是最重要的),我看像敵敵畏(啊啊,給我一杯敵敵畏,讓我不用寫程式........哈哈,我的水平直逼牛得滑了,好耍!好耍!)。然後你開始寫了一大堆你自認為不比“葵花寶典”差的驅動程式,嘿嘿,你發覺整個程式就是編譯不過去,就好像你花十塊零五毛RMB買了本“葵花寶典”,終於下定決心按照書的首頁要求的引刀什麼的,可是你發覺費了九馬二騾之力引完了刀,神功依舊未成,點解!你又得去學什麼程式調試,去Debug,俺們稱其為捉蟲,NN的,TMD,蟲沒有捉到,腦袋可腫的大大的。什麼SOFTICE,WINDBG之類,儘是一些系統殺手的角色,一不小心改錯了一個記憶體位址,哼,我CRASH你的機器,你只好又裝機,又調試,又死翹翹,你不見密西西比河不死心,又重來一遍,如此三番,惹得你無名火起,起身飲茶,又見隔壁部門的老闆正和小蜜在討論周末去哪裡加班工作,不由的氣不打一處出,大吼一聲“呔,來將何人!洒家張翼德在此!”..........哎,人在老闆下,哪能不幹活,只有硬頭再上.............無數次的失敗,無數次的徒勞之後,終於讓你的機器跑的歡極了,你不由的小哼一句“對面的小蜜看過來,這裡的男孩很能幹!”
驅動程式真的得看個人造化,若你有張無忌般奇遇,有韋小寶般豔福,有段輿般韌勁,(對了,還要有東方不敗般的勇氣)還有什麼做不了的。哈哈!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.