周德榮,夏 齡
(四川民族學(xué)院 網(wǎng)絡(luò)信息中心,四川 康定 6 2 6 0 0 1)
L i n u x platform驅(qū)動(dòng)架構(gòu)實(shí)現(xiàn)機(jī)制研究與應(yīng)用
周德榮,夏 齡
(四川民族學(xué)院 網(wǎng)絡(luò)信息中心,四川 康定 6 2 6 0 0 1)
Linux 2.6內(nèi)核開(kāi)發(fā)了全新的設(shè)備驅(qū)動(dòng)模型,實(shí)現(xiàn)了設(shè)備驅(qū)動(dòng)到總線和核心層的抽象,platform是基于新設(shè)備驅(qū)動(dòng)模型的虛擬總線.本文采用linux 2.6.25.8內(nèi)核源碼,介紹了設(shè)備驅(qū)動(dòng)模型原理,詳細(xì)分析了platform總線驅(qū)動(dòng)架構(gòu)在linux內(nèi)核中的實(shí)現(xiàn)機(jī)制,以TQ2440開(kāi)發(fā)板為測(cè)試平臺(tái),基于platform驅(qū)動(dòng)架構(gòu)設(shè)計(jì)實(shí)現(xiàn)了按鍵驅(qū)動(dòng).實(shí)驗(yàn)表明,此方法切實(shí)可行,驅(qū)動(dòng)具有較好植移性和安全性.
設(shè)備驅(qū)動(dòng)模型;platform;sysfs;按鍵驅(qū)動(dòng)
隨著技術(shù)的不斷進(jìn)步,系統(tǒng)的拓?fù)浣Y(jié)構(gòu)越來(lái)越復(fù)雜,系統(tǒng)支持的設(shè)備數(shù)量巨增,對(duì)智能電源管理、熱插拔以及p l u g a n dp l a y的支持要求也越來(lái)越高,為適應(yīng)這種形勢(shì)的需要,L i n u x2.6內(nèi)核開(kāi)發(fā)了全新的設(shè)備模型.L i n u x設(shè)備驅(qū)動(dòng)模型采用面向?qū)ο蟮乃枷耄瓿蓮脑O(shè)備驅(qū)動(dòng)到總線和核心層的抽象.platform是設(shè)備驅(qū)動(dòng)模型中基于設(shè)備驅(qū)動(dòng)模型核心層的一個(gè)虛擬總線,基于platform驅(qū)動(dòng)架構(gòu)驅(qū)動(dòng)設(shè)計(jì)方式在新版linux內(nèi)核中大量使用.
L i n u x設(shè)備驅(qū)動(dòng)模型是為了系統(tǒng)地管理所有設(shè)備,內(nèi)核通過(guò)k o b j e c t s和k s e t s底層數(shù)據(jù)結(jié)構(gòu)來(lái)實(shí)現(xiàn)基本對(duì)象及其層次關(guān)系,底層數(shù)據(jù)結(jié)構(gòu)之上實(shí)現(xiàn)的設(shè)備模型的核心組件總線,設(shè)備,驅(qū)動(dòng)結(jié)構(gòu)及相互操作.
1.1 底層關(guān)鍵數(shù)據(jù)結(jié)構(gòu)
設(shè)備驅(qū)動(dòng)模型底層主要涉及k o b j e c t內(nèi)核對(duì)象、K s e t內(nèi)核對(duì)象集合兩個(gè)數(shù)據(jù)結(jié)構(gòu).k o b j e c t是L i n u x2.6新引入的設(shè)備管理機(jī)制,是設(shè)備模型的核心結(jié)構(gòu),內(nèi)核中用s t r u c t k o bj e c t表示.k o b j e c t提供基本的對(duì)象管理能力,使所有設(shè)備在底層具有統(tǒng)一的接口.k o b j e c t主要完成對(duì)象的引用計(jì)數(shù)、s y s f s表示、數(shù)據(jù)結(jié)構(gòu)粘和、熱插拔事件處理功能.k o b j e c t結(jié)構(gòu)定義為:
k s e t是具有相同類型的k o b j e c t的集合,它有一套操作函數(shù),實(shí)現(xiàn)k s e t組織成層次化的結(jié)構(gòu)管理,內(nèi)核中用k s e t數(shù)據(jù)結(jié)構(gòu)表示.k s e t數(shù)據(jù)結(jié)構(gòu)定義為:
包含在k s e t中的所有k o b j e c t被組織成一個(gè)雙向循環(huán)鏈表l i s t.k s e t數(shù)據(jù)結(jié)構(gòu)內(nèi)嵌了一個(gè)k o b j e c t對(duì)象k o b j,所有屬于這個(gè)k s e t的k o b j e c t對(duì)象的p a r e n t域均指向這個(gè)內(nèi)嵌的對(duì)象.k s e t的引用計(jì)數(shù)依賴內(nèi)嵌的k o b j e c t對(duì)象的引用計(jì)數(shù)來(lái)實(shí)現(xiàn).u e v e n t_o p s域代表當(dāng)前u e v e n t的操作集合.
1.2 linux設(shè)備模型三要素
在底層數(shù)據(jù)結(jié)構(gòu)建立內(nèi)核對(duì)象管理機(jī)制的基礎(chǔ)上,L i nu x通過(guò)總線、設(shè)備、設(shè)備驅(qū)動(dòng)三個(gè)核心組件實(shí)現(xiàn)設(shè)備模型.總線作為主機(jī)和外設(shè)的連接通道,任何設(shè)備都可以選擇合適的總線連接到主機(jī),總線由s t r u c t bus_t y p e結(jié)構(gòu)描述,每個(gè)bus_t y p e對(duì)象都對(duì)應(yīng)/s y s/bus目錄下的一個(gè)子目錄.設(shè)備是連接在總線上的實(shí)體,不同設(shè)備功能不同.設(shè)備由device結(jié)構(gòu)描述.驅(qū)動(dòng)程序是C P U運(yùn)行時(shí),提供操作設(shè)備的軟件接口,所有設(shè)備必須配套驅(qū)動(dòng)程序才能正常工作.設(shè)備驅(qū)動(dòng)由device_driver結(jié)構(gòu)描述.總線,設(shè)備,設(shè)備驅(qū)動(dòng)三者關(guān)系如圖1所示.
L i n u x初始化時(shí),總線開(kāi)始掃描設(shè)備,找到設(shè)備就為其申請(qǐng)一個(gè)s t r u c t device結(jié)構(gòu),通過(guò)內(nèi)核函數(shù)將其加入總線中p->device s_k s e t鏈表;每個(gè)驅(qū)動(dòng)程序初始化時(shí),注冊(cè)s t r u c t device_driver結(jié)構(gòu),遍歷總線的p->device s_k s e t鏈表,去尋它所支持的設(shè)備,找到后把s t r u c t device中的s t r u c t device_driverdriver指向這個(gè)driver,而s t r u c tdevice_driver driver把s t r u c t device加入他的那張s t r u c t k l i s t k l i s t_device s鏈表.
1.3 s y s f s文件系統(tǒng)
s y s f s文件系統(tǒng)是linux設(shè)備模型的一個(gè)重要組成部分.s y s f s是一個(gè)在啟動(dòng)時(shí)加載到/s y s的內(nèi)存文件系統(tǒng),它用于將系統(tǒng)中的設(shè)備組織成層次結(jié)構(gòu),并向用戶模式程序提供詳細(xì)的內(nèi)核數(shù)據(jù)結(jié)構(gòu)信息.頂層目錄主要有包含所有的塊設(shè)備的B l o c k目錄、所有設(shè)備的D e v i c e s目錄、系統(tǒng)所有總線類型的B u s目錄、內(nèi)核中所有已注冊(cè)設(shè)備驅(qū)動(dòng)程序的D r i v e r s目錄、系統(tǒng)中設(shè)備類型的C l a s s目錄.
圖1 總線,設(shè)備,設(shè)備驅(qū)動(dòng)的關(guān)系
platform驅(qū)動(dòng)架構(gòu)是在Linux設(shè)備驅(qū)動(dòng)模型上實(shí)現(xiàn)的,是對(duì)總線,設(shè)備,驅(qū)動(dòng)進(jìn)行了再次封裝處理,Linux 2.6新近源碼中大部分驅(qū)動(dòng)程序采用方式對(duì)原來(lái)驅(qū)動(dòng)進(jìn)行了改寫(xiě),platform總線驅(qū)動(dòng)架構(gòu)在內(nèi)核中分platform總線生成,platform設(shè)備、plat form驅(qū)動(dòng)三部分實(shí)現(xiàn).
2.1 platform總線
platform總線是linux 2.6內(nèi)核加入的一種虛擬總線,它主要用于連接S O C上的片上資源.platform總線在內(nèi)核中用platform_bus_t y p e結(jié)構(gòu)表示,總線本身也是一個(gè)設(shè)備,L i n u x內(nèi)核用platform_bus結(jié)構(gòu)表示.linux內(nèi)核源碼d r i ve r/b a s e/platform.c中定義了plat f o r_bus和platform_bus_t y p e全局內(nèi)核對(duì)象.platform總線作為一個(gè)設(shè)備在系統(tǒng)啟動(dòng)時(shí)自動(dòng)創(chuàng)建,具體函數(shù)調(diào)用流程為:start_k e r n e l()->rest_init()->k e rn e l_init()->d o_basic_se t u p()->driver_init()->platform_bus_init().start_k e r n e l()、rest_init()、k e r n e l_init()和 d o_basic_se t u p()在init/m a i n.c中實(shí)現(xiàn).driver_init()在drivers/b a s e/init.c中實(shí)現(xiàn),platform_bus_init()在drivers/b a s e/platform.c中實(shí)現(xiàn).流程中最終是調(diào)用platform_bus_init()完成platform總線生成與注冊(cè),核心代碼如下所示.
2.2 platform設(shè)備與platform驅(qū)動(dòng)
platform設(shè)備作為特殊的獨(dú)立實(shí)體在系統(tǒng)中出現(xiàn),主要包括基于端口的設(shè)備、外圍總線的連接設(shè)備,以及大多數(shù)集成于S O C的控制器,它們通常都通過(guò)C P U總線直接尋址.內(nèi)核中platform設(shè)備用S t r u c tplatform_device結(jié)構(gòu)描述,platf o r m驅(qū)動(dòng)用platform_driver結(jié)構(gòu)描述,如圖2所示.platf o r m_device結(jié)構(gòu)由設(shè)備名稱n a m e、設(shè)備i d、設(shè)備d e v和資源r e s o u r c e組成,N a m e用作與驅(qū)動(dòng)進(jìn)行匹配,r e s o u r c e是設(shè)備使用的資源數(shù)據(jù),如I R Q,地址等.通過(guò)platform_add_device s()、platform_device_register()和 platform_device_add()函數(shù)將平臺(tái)設(shè)備注冊(cè)到platform總線.platform_driver完全遵照設(shè)備驅(qū)動(dòng)模型的約定,繼承了device_driver,并進(jìn)行了封裝,通過(guò)platform_driver_register()函數(shù)完成平臺(tái)驅(qū)動(dòng)注冊(cè),平臺(tái)驅(qū)動(dòng)注冊(cè)涉及的主要函數(shù)調(diào)用流程為:platform_driver_register()->driver_register()->bus_add_driver()->driver_a t t a c h()->bus_f o r_e a c h_d e v()->__driver_a t t a c h()->driver_probe_device()->really_probe()->d r v->probe()->driver_b o u n d().platform驅(qū)動(dòng)注冊(cè)的核心任務(wù)是在driver_probe_device()函數(shù)中通過(guò)d r v->bus->m a t c h()語(yǔ)句實(shí)現(xiàn)調(diào)用 platform總線的m a t c h()方法,判斷驅(qū)動(dòng)的名稱和設(shè)備的名稱是否相等,相等驅(qū)動(dòng)能處理指定設(shè)備,否則驅(qū)動(dòng)不能處理指定設(shè)備.然后通過(guò)在r e a ll y_probe()方法中執(zhí)行 d r v->probe(d e v)語(yǔ)句實(shí)現(xiàn)調(diào)用 platf o r m驅(qū)動(dòng)的probe()方法,完成綁定驅(qū)動(dòng)到設(shè)備.
3.1 硬件平臺(tái)資源
T Q 2 4 4 0是一個(gè)基于S 3 C 2 4 4 0的開(kāi)發(fā)測(cè)試平臺(tái),按鍵硬件原理如圖 3所示.S 3 c 2 4 4 0的 G P I O_F 0,G P I O_F 1,G P IO_F 2,G P I O_F 4作為輸入口,讀取按鍵狀態(tài),這四個(gè)I/O口分別使用外部中斷 E I N T 0,E I N T 1,E I N T 2,E I N T 4.當(dāng)按鍵松開(kāi)時(shí),I/O口處于高電平,得到邏輯1,當(dāng)按鍵按下時(shí),I/O被拉低,得到邏輯0.
圖3 T Q 2 4 4 0平臺(tái)按鍵原理圖
3.2 按鍵驅(qū)動(dòng)實(shí)現(xiàn)
通過(guò)platform總線架構(gòu)開(kāi)發(fā)設(shè)備驅(qū)動(dòng)流程是:首先定義platform_device,注冊(cè)platform_device,實(shí)現(xiàn)platform設(shè)備注冊(cè)到 platform總線.然后定義 platform_driver,注冊(cè) platf o r m_driver,實(shí)現(xiàn)編寫(xiě)platform驅(qū)動(dòng),并完成驅(qū)動(dòng)和設(shè)備的綁定.platform設(shè)備和platform驅(qū)動(dòng)分別使用不同的內(nèi)核模塊實(shí)現(xiàn).
3.2.1 platform設(shè)備實(shí)現(xiàn)
platform設(shè)備是注冊(cè)到platform總線的,使用s t r u c t platform_device定義平臺(tái)設(shè)備,然后通過(guò)在模塊初始化函數(shù)中調(diào)用platform_device_register()執(zhí)行平臺(tái)設(shè)備注冊(cè),平臺(tái)設(shè)備注冊(cè)成功后,在platform總線產(chǎn)生名稱為s 3 c 2 4 4 0-k e y的設(shè)備.平臺(tái)設(shè)備定義及注冊(cè)的核心代碼如下:
3.2.2 platform驅(qū)動(dòng)實(shí)現(xiàn)
platform驅(qū)動(dòng)的實(shí)現(xiàn)主要是定義一個(gè)s t r u c t platf o r m_driver類型的s 3 c 2 4 4 0_k e y_driver,并實(shí)現(xiàn)其成員,然后在模塊初始化函數(shù)中通過(guò)調(diào)用platform_driver_register()實(shí)現(xiàn)注冊(cè)平臺(tái)驅(qū)動(dòng)到platform總線.定義平臺(tái)驅(qū)動(dòng)的核心代碼如下:
在s 3 c 2 4 4 0_k e y_driver中s 3 c 2 4 4 0_k e y_probe()是完成查詢系統(tǒng)中是否有對(duì)應(yīng)的設(shè)備,有則完成驅(qū)動(dòng)的初始化工作.按鍵驅(qū)動(dòng)采用中斷方式實(shí)現(xiàn),每個(gè)按鍵對(duì)應(yīng)一個(gè)中斷,實(shí)現(xiàn)時(shí)對(duì)應(yīng)一個(gè)中斷處理函數(shù).在s 3 c 2 4 4 0_k e y_probe()函數(shù)中調(diào)用m i s c_register()將按鍵作為混亂驅(qū)動(dòng)向內(nèi)核注冊(cè),實(shí)現(xiàn)按鍵的 o p e n()、r e a d()、p o l l()和 c l o s e()功能,在 o p e n()函數(shù)中調(diào)用r e q u e s t_i r q()實(shí)現(xiàn)中斷處理函數(shù)與中斷號(hào)的綁定,當(dāng)按下一個(gè)鍵時(shí)中斷處理程序立即響應(yīng).s 3 c 2 4 4 0_k e y_probe()函數(shù)的核心代碼框架如下:
基于platform總線的驅(qū)動(dòng)機(jī)制與傳統(tǒng)的設(shè)備驅(qū)動(dòng)機(jī)制相比,platform總線的驅(qū)動(dòng)機(jī)制將設(shè)備本身的資源注冊(cè)進(jìn)內(nèi)核,由內(nèi)核統(tǒng)一管理,驅(qū)動(dòng)程序使用這些資源時(shí)使用platf o r m device提供的標(biāo)準(zhǔn)接口進(jìn)行申請(qǐng),提高了驅(qū)動(dòng)和資源管理的獨(dú)立性,具有較好的移植性和安全性.
〔1〕(印)Sreekrishnan Venkateswaran .Essential Linux Device Drivers[M].Prentice Hall PTR,2009.
〔2〕(美 )Jonathan Corbet,Alessandro Rubini,Greg Kroah-Hartman,魏永明譯.Linux設(shè)備驅(qū)動(dòng)程序 (第三版)[M].中國(guó)電力出版社,2006.
〔3〕宋寶華.Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解[M].人民郵電出版社,2008.
〔4〕李俊.嵌入式Linux設(shè)備驅(qū)動(dòng)開(kāi)發(fā)詳解[M].人民郵電出版社,2008.
〔5〕孫天澤,袁文菊,等.嵌入式設(shè)計(jì)及 Linux驅(qū)動(dòng)開(kāi)發(fā)指南——基于ARM 9處理器[M].電子工業(yè)出版社,2005.
〔6〕韋東山.嵌入式Linux應(yīng)用開(kāi)發(fā)完全手冊(cè)[M].人民郵電出版社,2008.
T P 3 0 3
A
1673-260X(2010)10-0028-03