專家門診:如何正確入門Windows系統驅動開發領域
我一直認為,編寫程序是一件很奇妙的事情,它可以帶來創造和控制的欲望。每當我閱讀或者編寫一段代碼時,腦子里自然地就會想象這段代碼怎樣完成預定的邏輯。對于代碼編寫者或者維護者來說,真正見功夫的地方不在于代碼本身,而在于對下層開發平臺的理解和駕馭能力,可能這就是俗稱的“內功”,這個觀點既適用于應用軟件程序員,也適用于系統軟件程序員。
本期門診特邀AMD公司知名Windows內核驅動開發領域專家張佩先生,針對WDM\WDF框架、USB設備驅動、設備驅動安裝等問題給予解答,歡迎網友積極提問,與專家一起討論!
專家著作:《竹林蹊徑:深入淺出Windows驅動開發》
本期門診鏈接:http://doctor.51cto.com/develop-213.html
本期專家:
張佩
Q:324120
windows 內核驅動是個什么情況?代碼嗎? 像一般的那種比較難找的USB驅動是該怎么驅上去的呢?謝謝
A:張佩
驅動兩個字是英文driver的翻譯,料來是很達意的。打比方說,一輛汽車,你買車會綜合考慮各種參數,驅動是發動機那一環,最基礎和頂重要的。其次要考量一下外形或內部裝修等,這就好像ui程序。開車的人一般不擔心發動機會出故障,而更當心車漆不要被刮了這類問題。因為發動機不容易壞,果真壞了,車子就非常危險。 驅動程序也一樣。你問驅動是代碼嗎?當然是了,只不過是頂重要和關鍵的代碼,在內核環境中運行,負責處理用戶程序請求。OS在內核中提供了很豐富的接口,用戶程序永遠無法使用它們,但Driver會仰賴它們來實現自己的各種功能。特別是和硬件交互。比如U盤讀寫,在用戶程序而言,到Read\WriteFile就算結束了,殊不知在內核還有重重關口要過。說到底,驅動程序是NT內核的補充,它像打到磚墻里的釘子一樣,被OS加載后,就成了和內核一體的了。內核關鍵而脆弱,能實現強大功能,也會不經然給個藍屏。所以安全第一,次而功能。
Q:CHO堯子
張老師:
您好。首先,我想問的針對筆記本電腦的顯卡驅動問題,為什么有時候無法安裝顯卡驅動,但是顯卡并沒有壞,在官網上也有驅動,型號是HP-CQ45,還有什么是WDM\WDF框架?我以前沒有聽說過呢!我還可以問下關于瀏覽器方面的問題么,有時候瀏覽器總是出現自動崩潰,沒有病毒,網速正常,是什么原因導致的?
A:張佩
你好。顯卡型號特別多,驅動安裝需對號入座,這個號就是設備id。這個id是寫在設備固件里面的,os讀出這個id并尋找匹配的驅動進行安裝。os很聰明,絕不會張冠李戴,所以你要說為什么驅動不能安裝或更新,首先要確定你下載了正確的安裝包。你要有本事,可以在安裝包中找一找inf文件,看看它支持你的顯卡否?可通過設備管理器查看你系統中顯卡的設備id。 這二者必須匹配才行。可以把設備ID理解成設備在PC中的個人身份證,我們不能因為兩塊顯卡是一家人(型號相同),而認為它們就是同一個人(設備ID可能不同)。
那么最后,我建議你懶一點,如果是win7系統的話,嘗試在設備管理器中右鍵選更新驅動,并讓它自己去網絡服務器上搜索有無新版驅動,或能解決你的問題。
Q:leo0087
張大哥,您好:
小弟很想知道WINDOWS和LINUX內核有什么區別?
張佩
你的問題很像一個面試題。一般面試的時候他們都會問我:)我不懂linux啊。微軟是龐大的軟件帝國,你應該曉得,有兩個截然不同的windows,一個是基于dos的win9x,一個是參照了dec的vms而開發出來的NT系統。現在用的是后者。
linux是類unix的操作系統,它大抵是一個孤憤之作,因為unix的版權所有者AT&t公司當時停止了unix的開源,并發起了一些訴訟官司。于是才有了linux和minix這類重造鍋爐的類 unix系統。說到二者的區別,千差萬別不為過吧。NT之父Cutler是滿懷著對unix的無比鄙視和憤怒開發出NT系統的,你可想而知。前者unix 類大抵使用單一內核,而后者NT基本算微內核吧,這是最典型的差別。當然,單一內核或微內核,二者都并不純粹,是互有參照的。
Q:zhang45xiang
您好:如同本期:如何正確入門Windows系統驅動開發領域 來說,如何進行系統驅動開發呢?當系統驅動存在沖突的時候如何解決,如何卸載干凈?
A:張佩
入門對各行各業都不是一個簡單回答的問題,請從基本做起吧,先熟悉起wdm/wdf這類基本框架,寫一些簡單的內核服務,演練起來,培養興趣和基礎。第二個問題,是不存在的。系統有自己選擇驅動的機制,哪有沖突的可能。這要你熟悉inf文件才可,要熟悉系統是怎么選Driver的,這樣你就不會困惑了。第三個問題,一言難盡呢。但就驅動程序而言,基本上只要在設備管理器中選擇刪除,它會把注冊表中相關的服務鍵、枚舉鍵刪除的,inf目錄中的 oemxx.inf也會刪除,這就夠了。失去這些信息,其他內容已不能工作。
Q:hagejid
買過一本天書夜讀,不過里邊介紹64位編程的內容太少了,不知道在64位下內核編程有什么要注意的地方。
A:張佩
朋友,竹林一書中關于64位編程的內容,已經免費放出來供下載,無數同學都在閱讀了,你何不網上也找來一讀?比我在這里費力地扯一兩句要有用多。
Q:manchester1878
菜鳥求問,系統漏洞的分析是不是必須要深入理解內核
張佩
菜鳥兄,我勸你和我一樣,暫且不要去分析系統漏洞了吧。那是很少一群人干的,靠那個能賺錢。你先不考慮吧,有空看起內核相關的一二本書,權當消遣,不是更好?
Q:baofeng1937
張老師:你好!
非常高興見到你!很想知道WDM/WDF框架在WDM中操作系統與內核的交互式和在WDF中的二者分離,如何保證系統與硬件的兼容性?
A:張佩
WDM/WDF的問題,簡而言之:WDF本質上是對wdm的封裝。一個WDF驅動分成兩個部分:WDK提供的基于WDM編寫的WDF框架代碼,和程序員基于此框架編寫的自己的代碼。
我先說前者WDF框架。WDF是基于WDM的封裝,意思是說,微軟WDK提供一個基于WDM的模板,在模板中完成基本代碼,或者復雜而累贅,或者艱難而生僻的代碼邏輯等等。這個模板就是名為WDF的框架,目前實現在文件wdf01000.sys中。再談后者:框架有了,裝修和細節還是要程序員自己來填充的,并且程序元需要根據定義好的框架來有序填充,這就是程序員自己的代碼。二者拼在一起,是一份完整的WDM驅動代碼。
理解了這種關系之后,我們就可以知道,WDM和WDF之間其實不存在任何兼容問題,只要系統中有WDF框架文件存在即可以了。
再講兩點:
1. WDM/WDF的關系,和前代兩種框架VxM與WDM間的關系是不一樣的,二者不互相兼容,因為WDM并不是基于VxM的封裝,完全不同;
2. 國內熟悉MFC開發的人特多,可以類比,MFC框架是對Win32編程的封裝,Win32/MFC的關系類同于WDM/WDF關系,你可以去想象。
Q:baofeng1937
張老師:
針對上面的usb驅動話題,我還想知道我們的移動存儲設備、USB類的鍵盤鼠標等,通過與系統的連接,是不是基于系統中的USB驅動程序進行運行,而本身有沒有裝驅動?如果沒有,那么類似u盤這類無法發現情況,是不是系統驅動的問題?如果有,那么它們又是怎樣與系統驅動進行交互執行的呢?
A:張佩
所有連接到主機的外設,都是由驅動程序驅動的,我沒有看到過特例。或者這樣說:凡是連接到系統總線(ACPI/PCI)上的設備,都會被系統枚舉并嘗試安裝驅動,無一例外。介紹你一個認識系統設備樹的簡單方法:命令行中敲入DevMgmt.msc命令,運行設備管理器程序;在View菜單中選擇“依連接排序設備”;你能看到一個名稱類似“X86 PC電腦”的根設備。展開這個設備后,就能看到一級級的子設備了。
另外,你問題里面提到的多種USB設備的驅動問題,答案非常簡單:這些設備一定是有驅動程序的,當然這些驅動程序往往都不用你自己去手動安裝,因為它們是普遍被使用的標準設備,微軟OS早就為它們準備了In-Box驅動,這些驅動在你的OS被安裝好后,就已經存在于系統目錄中了,當設備首次接入后會自動安裝這些In-Box驅動。另外,在這種情況下,這些標準USB設備的生產廠商也是可以編寫自己的驅動來代替OS的In-Box驅動的,至于怎么代替,話題扯遠了,這里不提。
Q:niceheart
張生,你好,請問一下windows內核具體怎么開發?windows 內核對計算機有哪些重要的作用?他的核心是什么?謝謝!
A:張佩
你提問中有三個問號,回答如下:
1. 我們這里只討論驅動開發,無能討論內核開發。
2. 你問內核對計算機有哪些重要作用。就像汽車,你說它座位以下部分對于這輛車子能夠正常跑起來,起個什么作用?
什么是內核?內核就是OS本身!我們平時的桌面,只是一個殼(Shell)而已。客觀上講,殼是可以被替換的(即Exporer.exe程序)。
3. 核心包含了很多內容,簡單而言,是:HAL模塊、執行體模塊、以及Win32子系統等。
Q:zr120633367
電腦打開其他文件夾很正常, 但打開指定的文件時卻反應半天就是假死的樣子。這是怎么回事呢?系統也重慶做過。
A:張佩
從你描述的現象很難給出答案,但我可以講一講。用戶在文件管理器中打開文件夾,在干凈的OS中,這個操作僅僅導致一系列的Open、Close、 QueryInformation等函數的調用,目地是請求系統返回文件夾中的所有文件的列表以及文件信息,從而桌面可以顯示它們,這些操作一般不會耗費很多時間。
至于為什么非常慢,以至于假死,我懷疑你安裝了某些軟件,這些軟件Hook了一些系統調用,會在你打開一個文件
或文件夾的時候,同時也對被打開的文件進行檢查操作。比如殺毒、木馬軟件,或者像SVN、CVS等軟件,都會這樣做。
如果你安裝了這些軟件,可以先把它們挺掉。如果懷疑中毒的話,用 IceSword軟件看看,它會檢測Hook情況。再教你做這樣一個實驗:去網上下載名為FileMon的工具,它能夠監測到所有的文件查詢、讀寫操作,你在Options菜單中設置Filter為你的文件夾路徑(比如C:\folder1),這樣FileMon只會檢測指定文件夾。然后你打開這個文件夾,FileMon會把所有操作記錄下來。你會發現有很多Log的工作進程是桌面進程(Explorer.exe),這是正常的。然后就要看看,是否有其它進程也在同時操作這個文件夾,FileMon會記錄操作發生時的時間,你可以據此做一些判斷。
Q:chilewang
張工 你好!
我想咨詢一下有關Windows下設備驅動開發的問題,目前我遇到一個問題是,如果設備斷電自己關機的話,如何避免上位機Windows系統的藍屏!
當我遇到這個問題時,我一直想象為什么DV機等這些USB設備在連接到電腦時,當關掉DV的電源時,電腦就不藍屏。而我的也是USB連接設備,可設備一失去電源,與其連接的電腦就要藍屏!如有描述不清,歡迎繼續與我聯系! 祝好~
A:張佩
很簡單,調試你的IRP_MJ_PNP/IRP_MN_SURPRISE_REMOVAL和IRP_MJ_POWER/ IRP_MN_SET_POWER這兩個分發函數。當設備突然移除的時候,會導致PNP和Set Power分發函數的調用。很顯然,你的驅動沒有處理好這些問題。
Q:dplm
張老師:你好。
請教一下U盤量產失敗,或有時不明原因,U盤出現0字節,非物理損壞。是使用的軟件有問題(或不持這個U盤),還是其它原因。理論上所有U盤都可以量產嗎?
用其它工具制作U盤啟動,如UltraISO,與量產技術之間有什么區別,實現的原理能簡單介紹一下嗎?
A:張佩
沒認真研究過,Sorry,所以我不知道我下面的理解是否正確:
量產工具應該是更新USB的ROM,或者刷固件,所以有些假U盤、移動硬盤,顯示出來是Apple公司生產的,淘寶上很多,拆開來看污七八糟。
UltraISO是改MBR扇區。本質上USB設備是沒有扇區概念的,但它可以假定自己有,這樣就可以實現U盤分區。
Q:sdbaby
你好張老師,我現在對于WINDOWS系統內核驅動,有一個想知道很久的問題!就是為什么WINDOWS98的時候(基于DOS下的系統)和 windows xp下的驅動 (基于NT系統) 前者有許多的驅動要自己安裝 ,但是XP系統就可以自動安裝上了!!!還有,上面的問題我們可以這樣想,是基于DOS和NT系統的區別,但是WINDOWS 2000應該也是基于NT系統下的吧?為什么有的驅動也要自行安裝呢???
張佩
如果有些驅動Win XP下不用手動安裝,而2K下需要手動安裝,這是由于2K系統沒有帶這些系統驅動,比如USB攝像頭(即UVC驅動usbvideo.sys)和所有 1394相關的驅動程序,就是例子。這些由系統自帶的驅動程序,或者某類默認設備驅動程序,我們稱之為In-Box驅動。對于負責驅動檢索、安裝的PNP管理器,2k和XP是沒有本質區別的。
Q:拿貝馬凡
hello,張工,我想咨詢下,nt內核中,鉤子(hook)的作用,另外內核鉤子與應用層鉤子有什么區別?另外他們與ssdt的關系,謝謝
A:張佩
實現Hook的技術很多,分析如下:
1. 系統鉤子,這是通過調用SetWindowsHook實現的。系統為某些消息專門準備了一個處理函數列表,調用這個函數,只是在列表中增加一項而已。
2. API鉤子。這種鉤子可以實現在用戶/內核層。原理不復雜,就是想辦法在讓Hook的函數調用你的函數,或者壓根用你的函數替代被Hook的函數。實現技術也分兩種:
一種:很多函數地址是以指針形成保存在內存里面的,比如IRP分發函數,或者你提到的SSDT表中的系統服務,以及IDT表中的ISR,可以找到保存函數支持的地址,然后用新地址替代它們;
第二:在實現好的函數中,插入jmp或者call指令,調用或跳轉到你的函數處執行,微軟自己就有一個名為動態更改的庫。
Q:wpp769
你好,我想請問下,我的筆記本系統剛裝好,在設備管理器里面網卡驅動有2個,但過幾天就變成5個了,而且3個都是帶感嘆號的,也就是說不可用。下載的網卡驅動也裝不上。我只能重做系統。請問這樣該怎么辦?能不能不做系統就解決呢?謝謝
A:張佩
筆記本有兩個網絡設備是正常的,一個是以太網,一個無線網;如果有五個,那么一定是你安裝了虛擬網卡,或者在安裝諸如虛擬機、VPN等軟件的時候,附帶安裝了這些虛擬網卡組件。你應當查看網絡設備名稱,并去網上搜索,會得到更多有用信息。
Q:Treasurecool
請問一下如何針對硬件進行驅動的開發,原理是什么啊,我是一個初學者,求解~~~
A:張佩
我不知道該怎么回答這個問題,我試著回答。
系統內核擁有和硬件通信的手段,即能夠讀寫設備寄存器、讀寫設備內存。通過這些硬件通信手段,系統能夠獲取設備信息,或對設備進行相關配置,以完成設備接入系統后的初始化操作。然后可進一步進行IO通信,這主要通過讀寫設備內存完成。
這些和硬件之間的操作極為底層,如果把這些操作都交給第三方來做,不容易。所以操作系統會完成大部分底層操作,而留出接口給上層的內核模塊調用。這些上層模塊,即內核驅動。一般驅動會有多個或多層,層層封裝,以讓由用戶自定義的驅動模塊盡量簡單。差不多這樣。
------------------------------------------
下期(200期)門診:Boost程序庫的應用探討
① 預告: Boost被稱為“C++準標準庫”,含有許多高質量的工具,如正則表達式、字符串算法、智能指針、散列容器等,彌補了C++98標準庫的不足,可以構建 出工業級強度的構件,代表了目前C++所能達到的最高技術高度。但Boost程序庫內容博大精深,又使用了大量的高級編程技巧,結構精致復雜,令不少程序 員望而生畏。
② 鏈接:http://doctor.51cto.com/develop-214.html