LINUX設(shè)備驅(qū)動(dòng)開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)_第1頁(yè)
LINUX設(shè)備驅(qū)動(dòng)開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)_第2頁(yè)
LINUX設(shè)備驅(qū)動(dòng)開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)_第3頁(yè)
LINUX設(shè)備驅(qū)動(dòng)開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)_第4頁(yè)
LINUX設(shè)備驅(qū)動(dòng)開(kāi)發(fā)經(jīng)驗(yàn)總結(jié)_第5頁(yè)
已閱讀5頁(yè),還剩115頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

嵌入式Linux驅(qū)動(dòng)開(kāi)發(fā)及內(nèi)核原理內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存硬件通訊塊設(shè)備驅(qū)動(dòng)中斷處理內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)設(shè)備驅(qū)動(dòng)簡(jiǎn)介

驅(qū)動(dòng)是什么Driverisasoftwarelayerthatliesbetweentheapplicationsandtheactualdevice驅(qū)動(dòng)程序的角色提供機(jī)制(方法),而不是策略(怎么用)隱藏在UNIX中的哲學(xué)mechanism:Whatcapabilitiesareprovided.policy:Howthesecapabilitiescanbeused.Kernel的作用Kernel可劃分為下列功能單元進(jìn)程管理:進(jìn)程調(diào)度,資源分配,進(jìn)程間通信.內(nèi)存管理:其實(shí)也算是資源分配的一部分文件系統(tǒng):管理,組織物理媒介上數(shù)據(jù)的方法設(shè)備控制:設(shè)備驅(qū)動(dòng)(linux驅(qū)動(dòng)開(kāi)發(fā)所關(guān)注的)網(wǎng)絡(luò):實(shí)質(zhì)上是進(jìn)程間通信.但它不局限于一個(gè)特定的進(jìn)程.它關(guān)注收/發(fā)packets,路由,地址解析...

Kernel的結(jié)構(gòu)模塊可加載模塊(lodablemodules)module:可實(shí)時(shí)加載到內(nèi)核中的代碼,它可動(dòng)態(tài)連接到內(nèi)核(insmod,rmmod)設(shè)備驅(qū)動(dòng)就是module的代表,但module還包括文件系統(tǒng)等等.

設(shè)備和模塊的分類(lèi)模塊分為這些類(lèi)型,每種類(lèi)型的模塊驅(qū)動(dòng)對(duì)應(yīng)類(lèi)型的設(shè)備charactermodule,blockmodule,networkinterfaceothermodule

字符設(shè)備和塊設(shè)備字符設(shè)備:以字節(jié)流的形式被訪問(wèn)的設(shè)備。e.g:/dev/console:文本控制臺(tái)./dev/ttyS0:串口它通過(guò)文件系統(tǒng)節(jié)點(diǎn)被訪問(wèn).e.g:/dev/tty1,/dev/lp0字符設(shè)備與一般文件(regularfile)的區(qū)別可以在一般文件中前后移動(dòng)(lseek),但只能順序訪問(wèn)字符設(shè)備.當(dāng)然,也有特例:framegrabbers.塊設(shè)備:能支持文件系統(tǒng)的設(shè)備傳統(tǒng)的UNIX:只能以block(512B)為單位訪問(wèn)塊設(shè)備 Linux:能以訪問(wèn)字符設(shè)備的方式訪問(wèn)塊設(shè)備,即以字節(jié)文單位訪問(wèn)塊設(shè)備.Linux中字符設(shè)備與塊設(shè)備的區(qū)別內(nèi)核內(nèi)部對(duì)數(shù)據(jù)的組織和管理不同,對(duì)驅(qū)動(dòng)開(kāi)發(fā)者來(lái)說(shuō)透明接口不同:使用兩套不同的interface網(wǎng)絡(luò)設(shè)備網(wǎng)絡(luò)接口:能與其他主機(jī)通信的設(shè)備它可以是硬件設(shè)備,也可以是軟件設(shè)備,比如lo.(參考TCP/IP詳解p26)網(wǎng)絡(luò)接口只管收發(fā)數(shù)據(jù)包,而不管這些數(shù)據(jù)包被什么協(xié)議所使用不同于字符設(shè)備和塊設(shè)備,網(wǎng)絡(luò)接口沒(méi)有對(duì)應(yīng)的文件系統(tǒng)節(jié)點(diǎn).雖然可以通過(guò)類(lèi)似eth0這樣的"文件名"來(lái)訪問(wèn)網(wǎng)絡(luò)接口,但文件系統(tǒng)節(jié)點(diǎn)中卻沒(méi)有針對(duì)網(wǎng)絡(luò)接口的節(jié)點(diǎn)內(nèi)核與網(wǎng)絡(luò)接口之間的通信也不同于內(nèi)核與字符/塊設(shè)備之間的通信(read,write),它們之間使用特定的傳輸數(shù)據(jù)包的函數(shù)調(diào)用其他設(shè)備也有一些module不能?chē)?yán)格地劃分類(lèi)型.USBmodule:它工作在內(nèi)核的USB子系統(tǒng)之上實(shí)際的USB設(shè)備可以是字符設(shè)備,塊設(shè)備,也可以是網(wǎng)絡(luò)接口在設(shè)備驅(qū)動(dòng)之外,別的功能,不論硬件和軟件,在內(nèi)核中都是模塊化的例如文件系統(tǒng)內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)建立和運(yùn)行模塊建立開(kāi)發(fā)環(huán)境ldd3例子開(kāi)發(fā)環(huán)境linux驅(qū)動(dòng)開(kāi)發(fā)需要預(yù)先安裝內(nèi)核源碼源碼需要從官方下載或者其他發(fā)行版的官方下載直接解壓到/usr/src目錄下版本影響內(nèi)核官方版本注意注意發(fā)行版的內(nèi)部版本最新內(nèi)核版本linux2.6.20/21工作隊(duì)列接口變化小版本變動(dòng)不會(huì)對(duì)驅(qū)動(dòng)的架構(gòu)造成太大影響對(duì)于不同發(fā)行版,不同內(nèi)核版本要做少量移植和測(cè)試內(nèi)核模塊VS應(yīng)用程序執(zhí)行機(jī)制不同模塊初始化模塊退出類(lèi)似事件編程使用庫(kù)不一樣無(wú)法使用標(biāo)準(zhǔn)庫(kù)只能調(diào)用內(nèi)核提供的函數(shù)用戶(hù)空間VS內(nèi)核空間用戶(hù)空間VS內(nèi)核空間應(yīng)用程序運(yùn)行在用戶(hù)空間設(shè)備模塊運(yùn)行在內(nèi)核空間運(yùn)行模式不一樣內(nèi)存地址映射也不一樣用戶(hù)空間和內(nèi)核空間的轉(zhuǎn)換可能發(fā)生在進(jìn)程中的系統(tǒng)調(diào)用時(shí)或者硬件中斷系統(tǒng)調(diào)用雖然在內(nèi)核中執(zhí)行,但是依然是在進(jìn)程的上下文中進(jìn)行的,所以可以訪問(wèn)到進(jìn)程中的數(shù)據(jù)。中斷處理和進(jìn)程是異步的了,而且不和任何進(jìn)程有關(guān)系模塊跨越兩個(gè)空間,有兩個(gè)觸發(fā)入口一些函數(shù)作為系統(tǒng)調(diào)用的一部分執(zhí)行一些函數(shù)負(fù)責(zé)中斷處理內(nèi)核中的并發(fā)應(yīng)用程序很多時(shí)候是按照順序來(lái)執(zhí)行的內(nèi)核處于并發(fā)的執(zhí)行環(huán)境當(dāng)中內(nèi)核當(dāng)中有并發(fā)的進(jìn)程中斷需要響應(yīng)和處理內(nèi)核中的服務(wù)也在運(yùn)行對(duì)稱(chēng)多處理器導(dǎo)致并行模塊的加載卸載和查看加載使用insmod卸載使用rmmod查看使用lsmod模塊代碼staticint__initinitialization_function(void){

/*initializationcodehere*/}module_init(initialization_function);模塊代碼staticvoid__exitcleanup_function(void){

/*Cleanupcodehere*/}module_exit(cleanup_function);如何處理加載中的失敗int__initmy_init_function(void){interr;/*registrationtakesapointerandaname*/err=register_this(ptr1,"skull");if(err)gotofail_this;err=register_that(ptr2,"skull");if(err)gotofail_that;err=register_those(ptr3,"skull");if(err)gotofail_those;return0;/*success*/fail_those:unregister_that(ptr2,"skull");fail_that:unregister_this(ptr1,"skull");fail_this:returnerr;/*propagatetheerror*/}如何編寫(xiě)清理函數(shù)void__exitmy_cleanup_function(void){unregister_those(ptr3,"skull");unregister_that(ptr2,"skull");unregister_this(ptr1,"skull");return;}內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)主次設(shè)備號(hào)字符設(shè)備可以通過(guò)文件系統(tǒng)來(lái)存取字符設(shè)備一般位于/dev下有c標(biāo)志的是字符設(shè)備有b標(biāo)志的是塊設(shè)備設(shè)備號(hào)文檔Documentation/devices.txt主設(shè)備號(hào)決定驅(qū)動(dòng)的種類(lèi)次設(shè)備號(hào)決定使用哪個(gè)設(shè)備設(shè)備編號(hào)的內(nèi)部表達(dá)dev_t類(lèi)型(在<linux/types.h>中定義)用來(lái)持有設(shè)備編號(hào)--主次部分都包括獲得一個(gè)dev_t的主或者次編號(hào),使用MAJOR(dev_tdev);MINOR(dev_tdev);轉(zhuǎn)換為一個(gè)dev_t,使用:MKDEV(intmajor,intminor);分配和釋放設(shè)備編號(hào)分配指定的主設(shè)備號(hào)intregister_chrdev_region(dev_tfirst,unsignedintcount,char*name);動(dòng)態(tài)分配主設(shè)備號(hào)intalloc_chrdev_region(dev_t*dev,unsignedintfirstminor,unsignedintcount,char*name);釋放

voidunregister_chrdev_region(dev_tfirst,unsignedintcount);字符驅(qū)動(dòng)中重要的數(shù)據(jù)結(jié)構(gòu)file_operationsfileinode字符設(shè)備的注冊(cè)在Linux2.6下使用“structcdev”記錄字符設(shè)備的信息。結(jié)構(gòu)定義如下:

structcdev{

structmodule*owner;

structfile_operations*ops;

dev_tdev;

};voidcdev_init(structcdev*,structfile_operations*);structcdev*cdev_alloc(void);intcdev_add(structcdev*,dev_t,unsigned)voidcdev_del(structcdev*);

Open方法檢查設(shè)備的特定錯(cuò)誤如果設(shè)備是首次打開(kāi),則對(duì)其進(jìn)行初始化如有必要,更新f_op指針?lè)峙淝姨顚?xiě)filp->private_data里的數(shù)據(jù)結(jié)構(gòu)Release方法釋放由open分配的,保存在filp->private中的所有內(nèi)容在最后一次關(guān)閉操作時(shí)關(guān)閉設(shè)備內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)通過(guò)打印調(diào)試通過(guò)宏可以定義日志級(jí)別KERN_EMERG用于緊急消息,常常是那些崩潰前的消息.KERN_ALERT需要立刻動(dòng)作的情形.KERN_CRIT嚴(yán)重情況,常常與嚴(yán)重的硬件或者軟件失效有關(guān).KERN_ERR用來(lái)報(bào)告錯(cuò)誤情況;設(shè)備驅(qū)動(dòng)常常使用KERN_ERR來(lái)報(bào)告硬件故障.KERN_WARNING有問(wèn)題的情況的警告,這些情況自己不會(huì)引起系統(tǒng)的嚴(yán)重問(wèn)題.KERN_NOTICE正常情況,但是仍然值得注意.在這個(gè)級(jí)別一些安全相關(guān)的情況會(huì)報(bào)告.KERN_INFO信息型消息.在這個(gè)級(jí)別,很多驅(qū)動(dòng)在啟動(dòng)時(shí)打印它們發(fā)現(xiàn)的硬件的信息.KERN_DEBUG用作調(diào)試消息.printk語(yǔ)句缺省是DEFAULT_MESSAGE_LOGLEVEL(KERN_WARNING)通過(guò)打印調(diào)試如果開(kāi)啟Klogd及Syslogd則輸出到日志日志文件參考/var/log/message在printk當(dāng)中打印設(shè)備編號(hào)Print_dev_tFormat_dev_t內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)并發(fā)和管理并發(fā)源很多多個(gè)進(jìn)程運(yùn)行SMP多個(gè)CPU并行設(shè)備中斷延遲機(jī)制(工作隊(duì)列,定時(shí)器,Tasklet)并發(fā)和競(jìng)爭(zhēng)兩個(gè)或多個(gè)進(jìn)程讀寫(xiě)某些共享數(shù)據(jù),而最后的結(jié)果取決于進(jìn)程運(yùn)行的精確時(shí)序,就稱(chēng)為競(jìng)爭(zhēng)條件(RaceConditions)。競(jìng)爭(zhēng)情況來(lái)自對(duì)資源的共享存取的結(jié)果.存取管理的常用技術(shù)是加鎖或者互斥其次常用的技術(shù)是引用計(jì)數(shù)臨界區(qū)把對(duì)共享內(nèi)存進(jìn)行訪問(wèn)的程序片段稱(chēng)作臨界區(qū)(criticalregion),或臨界段(criticalsection)。如果我們能夠適當(dāng)?shù)匕才攀沟脙蓚€(gè)進(jìn)程不可能同時(shí)處于臨界區(qū),則就能夠避免競(jìng)爭(zhēng)條件。臨界區(qū)四要素任何兩個(gè)進(jìn)程不能同時(shí)處于臨界區(qū)臨界區(qū)外的進(jìn)程不能阻塞其他進(jìn)程不能使進(jìn)程在臨界區(qū)外無(wú)限等待不應(yīng)對(duì)CPU的速度和數(shù)目做假設(shè)PV操作解決同步互斥PV原語(yǔ)的含義

P操作和V操作是不可中斷的程序段,稱(chēng)為原語(yǔ)。PV原語(yǔ)及信號(hào)量的概念都是由荷蘭科學(xué)家E.W.Dijkstra提出的。信號(hào)量sem是一整數(shù),sem大于等于零時(shí)代表可供并發(fā)進(jìn)程使用的資源實(shí)體數(shù),但sem小于零時(shí)則表示正在等待使用臨界區(qū)的進(jìn)程數(shù)。

P原語(yǔ)操作的動(dòng)作是:

(1)sem減1;

(2)若sem減1后仍大于或等于零,則進(jìn)程繼續(xù)執(zhí)行;

(3)若sem減1后小于零,則該進(jìn)程被阻塞后進(jìn)入與該信號(hào)相對(duì)應(yīng)的隊(duì)列中,然后轉(zhuǎn)進(jìn)程調(diào)度。

V原語(yǔ)操作的動(dòng)作是:

(1)sem加1;

(2)若相加結(jié)果大于零,則進(jìn)程繼續(xù)執(zhí)行;

(3)若相加結(jié)果小于或等于零,則從該信號(hào)的等待隊(duì)列中喚醒一等待進(jìn)程,然后再返回原進(jìn)程繼續(xù)執(zhí)行或轉(zhuǎn)進(jìn)程調(diào)度。

PV操作對(duì)于每一個(gè)進(jìn)程來(lái)說(shuō),都只能進(jìn)行一次,而且必須成對(duì)使用。在PV原語(yǔ)執(zhí)行期間不允許有中斷的發(fā)生。

解決互斥用PV原語(yǔ)實(shí)現(xiàn)進(jìn)程的互斥由于用于互斥的信號(hào)量sem與所有的并發(fā)進(jìn)程有關(guān),所以稱(chēng)之為公有信號(hào)量。公有信號(hào)量的值反映了公有資源的數(shù)量。只要把臨界區(qū)置于P(sem)和V(sem)之間,即可實(shí)現(xiàn)進(jìn)程間的互斥。就象火車(chē)中的每節(jié)車(chē)廂只有一個(gè)衛(wèi)生間,該車(chē)廂的所有旅客共享這個(gè)公有資源:衛(wèi)生間,所以旅客間必須互斥進(jìn)入衛(wèi)生間,只要把衛(wèi)生間放在P(sem)和V(sem)之間,就可以到達(dá)互斥的效果。

解決同步用PV原語(yǔ)實(shí)現(xiàn)進(jìn)程的同步與進(jìn)程互斥不同,進(jìn)程同步時(shí)的信號(hào)量只與制約進(jìn)程及被制約進(jìn)程有關(guān)而不是與整組并發(fā)進(jìn)程有關(guān),所以稱(chēng)該信號(hào)量為私有信號(hào)量。利用PV原語(yǔ)實(shí)現(xiàn)進(jìn)程同步的方法是:首先判斷進(jìn)程間的關(guān)系為同步的,且為各并發(fā)進(jìn)程設(shè)置私有信號(hào)量,然后為私有信號(hào)量賦初值,最后利用PV原語(yǔ)和私有信號(hào)量規(guī)定各進(jìn)程的執(zhí)行順序。Linux信號(hào)量實(shí)現(xiàn)voidsema_init(structsemaphore*sem,intval);DECLARE_MUTEX(name);DECLARE_MUTEX_LOCKED(name);voidinit_MUTEX(structsemaphore*sem);voidinit_MUTEX_LOCKED(structsemaphore*sem);voiddown(structsemaphore*sem);intdown_interruptible(structsemaphore*sem);intdown_trylock(structsemaphore*sem);voidup(structsemaphore*sem);內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)ioctl接口大部分驅(qū)動(dòng)需要通過(guò)設(shè)備驅(qū)動(dòng)進(jìn)行各種硬件控制的能力.大部分設(shè)備可進(jìn)行超出簡(jiǎn)單的數(shù)據(jù)傳輸之外的操作;例如,設(shè)備鎖上它的門(mén),彈出它的介質(zhì),報(bào)告錯(cuò)誤信息,改變波特率,或者自我銷(xiāo)毀.這些操作常常通過(guò)ioctl方法來(lái)支持,它通過(guò)相同名字的系統(tǒng)調(diào)用來(lái)實(shí)現(xiàn).阻塞I/O數(shù)據(jù)操作可能會(huì)遇到read的調(diào)用時(shí)可能沒(méi)有數(shù)據(jù)時(shí)Write的調(diào)用時(shí)設(shè)備沒(méi)有準(zhǔn)備好接受數(shù)據(jù)當(dāng)驅(qū)動(dòng)不能立刻滿(mǎn)足要求怎么辦程序員希望調(diào)用read或write并且使調(diào)用返回驅(qū)動(dòng)應(yīng)當(dāng)(缺省地)阻塞進(jìn)程,使它進(jìn)入睡眠直到請(qǐng)求可繼續(xù).進(jìn)程的休眠進(jìn)程被置為睡眠,從調(diào)度器的運(yùn)行隊(duì)列移除睡眠的進(jìn)程被擱置一邊,等待以后發(fā)生事件睡眠注意安全編程在原子上下文時(shí)不能睡眠休眠醒來(lái),無(wú)法確定休眠時(shí)間和時(shí)序休眠的進(jìn)程必須有時(shí)機(jī)被喚醒與休眠相關(guān)的數(shù)據(jù)結(jié)構(gòu)和函數(shù)等待隊(duì)列等待-喚醒函數(shù)wait_event(queue,condition)wait_event_interruptible(queue,condition)wait_event_timeout(queue,condition,timeout)wait_event_interruptible_timeout(queue,condition,timeout)voidwake_up(wait_queue_head_t*queue);voidwake_up_interruptible(wait_queue_head_t*queue);阻塞操作的推薦用法阻塞操作標(biāo)準(zhǔn)語(yǔ)法:如果一個(gè)進(jìn)程調(diào)用read但是沒(méi)有數(shù)據(jù)可用(尚未),這個(gè)進(jìn)程必須阻塞.這個(gè)進(jìn)程在有數(shù)據(jù)達(dá)到時(shí)被立刻喚醒,并且那個(gè)數(shù)據(jù)被返回給調(diào)用者,即便小于在給方法的count參數(shù)中請(qǐng)求的數(shù)量.如果一個(gè)進(jìn)程調(diào)用write并且在緩沖中沒(méi)有空間,這個(gè)進(jìn)程必須阻塞,并且它必須在一個(gè)與用作read的不同的等待隊(duì)列中.當(dāng)一些數(shù)據(jù)被寫(xiě)入硬件設(shè)備,并且在輸出緩沖中的空間變空閑,這個(gè)進(jìn)程被喚醒并且寫(xiě)調(diào)用成功,盡管數(shù)據(jù)可能只被部分寫(xiě)入,這時(shí)緩沖內(nèi)沒(méi)有足夠空間給被請(qǐng)求的count字節(jié).非阻塞I/O,poll和select可以實(shí)現(xiàn)非阻塞讀寫(xiě)多個(gè)文件三者的區(qū)別和聯(lián)系select在BSDUnix中引入poll是SystemV的解決方案epoll擴(kuò)展到幾千個(gè)文件描述符,提高了性能內(nèi)部實(shí)現(xiàn)

unsignedint(*poll)(structfile*filp,poll_table*wait);內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)測(cè)量時(shí)間流失內(nèi)核通過(guò)定時(shí)器中斷來(lái)跟蹤時(shí)間的流動(dòng)定時(shí)器中斷由系統(tǒng)定時(shí)硬件以規(guī)律地間隔產(chǎn)生每次發(fā)生一個(gè)時(shí)鐘中斷,一個(gè)內(nèi)核計(jì)數(shù)器的值遞增.這個(gè)計(jì)數(shù)器在系統(tǒng)啟動(dòng)時(shí)初始化為0,因此它代表從最后一次啟動(dòng)以來(lái)的時(shí)鐘嘀噠的數(shù)目這個(gè)計(jì)數(shù)器是一個(gè)64-位變量(即便在32-位的體系上)并且稱(chēng)為jiffies_64獲知當(dāng)前時(shí)間voiddo_gettimeofday(structtimeval*tv);延后執(zhí)行長(zhǎng)延時(shí)技術(shù)忙等待讓出處理器超時(shí)短延時(shí)技術(shù)voidndelay(unsignedlongnsecs);voidudelay(unsignedlongusecs);voidmdelay(unsignedlongmsecs);

內(nèi)核定時(shí)器structtimer_list{/*...*/unsignedlongexpires;void(*function)(unsignedlong);unsignedlongdata;};voidinit_timer(structtimer_list*timer);structtimer_listTIMER_INITIALIZER(_function,_expires,_data);voidadd_timer(structtimer_list*timer);intdel_timer(structtimer_list*timer);Tasklets機(jī)制structtasklet_struct{/*...*/void(*func)(unsignedlong);unsignedlongdata;};voidtasklet_init(structtasklet_struct*t,void(*func)(unsignedlong),unsignedlongdata);DECLARE_TASKLET(name,func,data);DECLARE_TASKLET_DISABLED(name,func,data);Tasklet特性一個(gè)tasklet能夠被禁止并且之后被重新使能;它不會(huì)執(zhí)行直到它被使能與被禁止相同的的次數(shù).如同定時(shí)器,一個(gè)tasklet可以注冊(cè)它自己.一個(gè)tasklet能被調(diào)度來(lái)執(zhí)行以正常的優(yōu)先級(jí)或者高優(yōu)先級(jí).后一組一直是首先執(zhí)行.taslet可能立刻運(yùn)行,如果系統(tǒng)不在重載下,但是從不會(huì)晚于下一個(gè)時(shí)鐘嘀噠.一個(gè)tasklet可能和其他tasklet并發(fā),但是對(duì)它自己是嚴(yán)格地串行的--同樣的tasklet從不同時(shí)運(yùn)行在超過(guò)一個(gè)處理器上.同樣,如已經(jīng)提到的,一個(gè)tasklet常常在調(diào)度它的同一個(gè)CPU上運(yùn)行.工作隊(duì)列工作隊(duì)列表面類(lèi)似于tasketstasklet在軟件中斷上下文中運(yùn)行的結(jié)果是所有的tasklet代碼必須是原子的.相反,工作隊(duì)列函數(shù)在一個(gè)特殊內(nèi)核進(jìn)程上下文運(yùn)行;結(jié)果,它們有更多的靈活性.特別地,工作隊(duì)列函數(shù)能夠睡眠.tasklet常常在它們最初被提交的處理器上運(yùn)行.工作隊(duì)列以相同地方式工作內(nèi)核代碼可以請(qǐng)求工作隊(duì)列函數(shù)被延后一個(gè)明確的時(shí)間間隔.工作隊(duì)列structworkqueue_struct*create_workqueue(constchar*name);structworkqueue_struct*create_singlethread_workqueue(constchar*name);

內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作內(nèi)存管理與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)內(nèi)存分配內(nèi)存分配的最常用接口.#include<linux/slab.h>void*kmalloc(size_tsize,intflags);voidkfree(void*obj);內(nèi)存管理功能程序在尋址過(guò)程中使用的是虛擬地址,該地址由段和偏移值該地址并不能直接用。為了能尋址物理內(nèi)存,就需要一種地址變換機(jī)制將虛擬地址映射或變換到物理內(nèi)存中,這種地址變換機(jī)制就是內(nèi)存管理的主要功能之一(內(nèi)存管理的另外一個(gè)主要功能是內(nèi)存的尋址保護(hù)機(jī)制。由于時(shí)間有限限,本次不對(duì)其進(jìn)行討論)。內(nèi)存管理機(jī)制1.無(wú)內(nèi)存管理,直接尋址,也稱(chēng)為實(shí)地址模式(內(nèi)存不受保護(hù))2.段式管理,也稱(chēng)為保護(hù)模式(可分段記錄內(nèi)存的使用情況)3.分頁(yè)式管理,目前操作系統(tǒng)使用的模式(可提高管理效率)分頁(yè)式管理(一)內(nèi)存分頁(yè)管理是通過(guò)頁(yè)目錄表和內(nèi)存頁(yè)表所組成的二級(jí)表進(jìn)行的。其中頁(yè)目錄表和頁(yè)表的結(jié)構(gòu)是一樣的,表項(xiàng)結(jié)構(gòu)也相同。頁(yè)目錄表中的每個(gè)表項(xiàng)(簡(jiǎn)稱(chēng)頁(yè)目錄項(xiàng))(4字節(jié))用來(lái)尋址一個(gè)頁(yè)表,而每個(gè)頁(yè)表項(xiàng)(4字節(jié))用來(lái)指定一頁(yè)物理內(nèi)存頁(yè)。因此,當(dāng)指定了一個(gè)頁(yè)目錄項(xiàng)和一個(gè)頁(yè)表項(xiàng),我們就可以唯一地確定所對(duì)應(yīng)的物理內(nèi)存頁(yè)。頁(yè)目錄表占用一頁(yè)內(nèi)存,因此最分頁(yè)式管理(二)頁(yè)目錄表有1024個(gè)表項(xiàng),每個(gè)表項(xiàng)占用4個(gè)字節(jié),所以一個(gè)頁(yè)目錄表剛好占用一頁(yè)內(nèi)存(4X1024),因此最多可以尋址1024個(gè)頁(yè)表。而每個(gè)頁(yè)表也同樣占用一頁(yè)內(nèi)存,因此一個(gè)頁(yè)表可以尋址最多1024個(gè)物理內(nèi)存頁(yè)面。這樣一個(gè)頁(yè)目錄表所尋址的所有頁(yè)表共可以尋址1024X1024X4096=4G的內(nèi)存空間頁(yè)目錄表和頁(yè)表結(jié)構(gòu)線性地址內(nèi)存分配所獲取的都是線性地址;一個(gè)32位的線性地址被分成了三個(gè)部分第一部分(10位):指定一個(gè)頁(yè)目錄項(xiàng)第二部分(10位):指定一個(gè)頁(yè)表項(xiàng)第三部分(12位):指定物理內(nèi)存頁(yè)上的偏移地址線性地址結(jié)構(gòu)(一)Typededstruct{ unsignedintdir:10/*用作頁(yè)面表目錄中的下標(biāo),該目錄項(xiàng)指向一個(gè)頁(yè)面表*/ unsignedintpage:10/*用作頁(yè)面表中的下標(biāo),該表項(xiàng)指向一個(gè)物理頁(yè)面*/unsignedintoffset:12/*用作4k字節(jié)物理頁(yè)面內(nèi)的偏移量*/}線性地址線性地址結(jié)構(gòu)(二)在頁(yè)面目錄中共有210

=1024個(gè)目錄項(xiàng),每個(gè)目錄項(xiàng)指向一個(gè)頁(yè)面表,每個(gè)頁(yè)面表共有1024個(gè)頁(yè)面描述項(xiàng)。線性地址的位31-22共10個(gè)比特用來(lái)確定頁(yè)目錄中的目錄項(xiàng),位21-12用來(lái)尋址頁(yè)目錄項(xiàng)指定的頁(yè)表中的頁(yè)表項(xiàng),最后的12個(gè)比特正好用作頁(yè)表項(xiàng)指定的一頁(yè)物理內(nèi)存中的偏移地址線性地址到物理地址映射(一)有專(zhuān)門(mén)的寄存器CR3存儲(chǔ)當(dāng)前頁(yè)面目錄的地址1.從寄存器CR3中取得頁(yè)面目錄的基地址2.以線性地址中的dir位段為下標(biāo),在目錄中取得相應(yīng)也表的基地址3.以線性地址中的page位段為下標(biāo),在所得到的頁(yè)面表中取得相應(yīng)的頁(yè)面描述項(xiàng)4.將頁(yè)面描述項(xiàng)中給出的頁(yè)面基地址與線性地址中的offset位段相加得到實(shí)際的物理地址線性地址到物理地址映射(二)線性地址到物理地址映射(三)線性地址到物理地址映射(四)對(duì)于第一個(gè)進(jìn)程(任務(wù)0),其頁(yè)表是在頁(yè)目錄表之后,共4頁(yè)。對(duì)于應(yīng)用程序的進(jìn)程,其頁(yè)表所使用的內(nèi)存是在進(jìn)程創(chuàng)建時(shí)向內(nèi)存管理程序申請(qǐng)的,因此是在主內(nèi)存區(qū)中表項(xiàng)結(jié)構(gòu)(一)頁(yè)框地址(PAGEFRAMEADDRESS)指定了一頁(yè)內(nèi)存的物理起始地址。因?yàn)閮?nèi)存頁(yè)是位于4K邊界上的,這些指針的低12位都永遠(yuǎn)是0。這樣,在目錄項(xiàng)和頁(yè)表項(xiàng)中都只要有20位用于指針就夠了,而余下的12位則可以用于控制或其他的目的用。表項(xiàng)結(jié)構(gòu)(二)每個(gè)表項(xiàng)由頁(yè)框地址、訪問(wèn)標(biāo)志位、臟(已改寫(xiě))標(biāo)志位和存在標(biāo)志位等構(gòu)成表項(xiàng)結(jié)構(gòu)(三)表項(xiàng)結(jié)構(gòu)(四)頁(yè)框地址(PAGEFRAMEADDRESS)指定了一頁(yè)內(nèi)存的物理起始地址存在位(PRESENT–P)確定了一個(gè)頁(yè)表項(xiàng)是否可以用于地址轉(zhuǎn)換。P=1可用,P=0不能用于地址轉(zhuǎn)換,相應(yīng)的頁(yè)面或頁(yè)面表不在內(nèi)存.CPU會(huì)產(chǎn)生缺頁(yè)中斷,內(nèi)核中表項(xiàng)結(jié)構(gòu)(五)P=0表示相應(yīng)的頁(yè)面或頁(yè)面表不在內(nèi)存.CPU會(huì)產(chǎn)生缺頁(yè)中斷,內(nèi)核中的有關(guān)異常服務(wù)程序就可根據(jù)從磁盤(pán)上的頁(yè)面交換區(qū)將相應(yīng)的頁(yè)面讀入內(nèi)存,并且相應(yīng)的設(shè)置表現(xiàn)中的基地址,并將P位設(shè)置為1,供后續(xù)訪問(wèn)使用。相反也可將內(nèi)存中暫時(shí)不使用的內(nèi)存頁(yè)面寫(xiě)入到磁盤(pán)的交換區(qū),然后將相應(yīng)的頁(yè)面表項(xiàng)的P位設(shè)置為0。這就實(shí)現(xiàn)虛擬內(nèi)存功能表項(xiàng)結(jié)構(gòu)(六)當(dāng)P=0時(shí),表項(xiàng)中的其余各位均無(wú)意義,所以可以被用來(lái)臨時(shí)存儲(chǔ)其他信息,如被換出的頁(yè)面在磁盤(pán)上的位置等等信息PS=0時(shí)表示包含在由該目錄項(xiàng)所指的頁(yè)面面表中所有頁(yè)面的大小都是4K字節(jié),這也是目前在Linux內(nèi)核中所采用的頁(yè)面大小。但從Pentium處理器開(kāi)始,intel引入了PSE頁(yè)面大小擴(kuò)充機(jī)制。即當(dāng)PS=1,頁(yè)面的大小就成了4M字節(jié),而頁(yè)面表就不足使用。表項(xiàng)結(jié)構(gòu)(七)Ps=1時(shí)線性地址中的低22位就全部用在4M字節(jié)的頁(yè)面中的位移,這樣總的尋址能力不變1024X4M=4G,但映射過(guò)程減少了一層。提高訪問(wèn)速度(主要是由于內(nèi)存容量和磁盤(pán)的容量的日益增加,磁盤(pán)訪問(wèn)速度的顯著提高,以及對(duì)圖像處理要求的日益增加,4M頁(yè)面可能成為主流)表項(xiàng)結(jié)構(gòu)(八)已訪問(wèn)(Accessed–A)和已修改(Dirty–D)比特位用于提供有關(guān)頁(yè)使用的信息。除了頁(yè)目錄項(xiàng)中的已修改位,這些比特位將由硬件置位,但不復(fù)位。在對(duì)一頁(yè)內(nèi)存進(jìn)行讀或?qū)懖僮髦埃珻PU將設(shè)置相關(guān)的目錄和二級(jí)頁(yè)表項(xiàng)的已訪問(wèn)位。在向一個(gè)二級(jí)頁(yè)表項(xiàng)所涵蓋的地址進(jìn)行寫(xiě)操作之前,處理器將設(shè)置該二級(jí)頁(yè)表項(xiàng)的已修改位,而頁(yè)目錄項(xiàng)中的已修改位是不用的。當(dāng)所需求的內(nèi)存超出實(shí)際物理內(nèi)存量時(shí),內(nèi)存管理程序就可以使用這些位來(lái)確定那些頁(yè)可以從內(nèi)存中取走,以騰出空間。內(nèi)存管理程序還需負(fù)責(zé)檢測(cè)和復(fù)位這些比特位表項(xiàng)結(jié)構(gòu)(九)讀/寫(xiě)位(Read/Write–R/W)和用戶(hù)/超級(jí)用戶(hù)位(User/Supervisor–U/S)并不用于地址轉(zhuǎn)換,但用于分頁(yè)級(jí)的保護(hù)機(jī)制,是由CPU在地址轉(zhuǎn)換過(guò)程中同時(shí)操作的。Linux中物理內(nèi)存的管理和分配物理地址0處存放了一個(gè)頁(yè)目錄表,緊隨其后是4個(gè)頁(yè)表。這4個(gè)頁(yè)表將被用于任務(wù)0,其它的派生進(jìn)程將在主內(nèi)存區(qū)申請(qǐng)內(nèi)存頁(yè)來(lái)存放自己的頁(yè)表控制內(nèi)存分配如何進(jìn)行的標(biāo)志,從最少限制的到最多的.GFP_USER和GFP_KERNEL優(yōu)先級(jí)允許當(dāng)前進(jìn)程被置為睡眠來(lái)滿(mǎn)足請(qǐng)求.GFP_NOFS和GFP_NOIO禁止文件系統(tǒng)操作和所有的I/O操作,分別地,而GFP_ATOMIC分配根本不能睡眠.#include<linux/mm.h>GFP_USERGFP_KERNELGFP_NOFSGFP_NOIOGFP_ATOMIC內(nèi)存分配標(biāo)志這些標(biāo)志分配內(nèi)存時(shí)修改內(nèi)核的行為_(kāi)_GFP_DMA__GFP_HIGHMEM__GFP_COLD__GFP_NOWARN__GFP_HIGH__GFP_REPEAT__GFP_NOFAIL__GFP_NORETRYslab緩存創(chuàng)建和銷(xiāo)毀一個(gè)slab緩存.這個(gè)緩存可被用來(lái)分配幾個(gè)相同大小的對(duì)象.#include<linux/malloc.h>kmem_cache_t*kmem_cache_create(char*name,size_tsize,size_toffset,unsignedlongflags,constructor(),destructor());intkmem_cache_destroy(kmem_cache_t*cache);緩存標(biāo)志在創(chuàng)建一個(gè)緩存時(shí)可指定的標(biāo)志.SLAB_CTOR_ATOMICSLAB_CTOR_CONSTRUCTOR緩存中分配釋放單個(gè)對(duì)象從緩存中分配和釋放一個(gè)單個(gè)對(duì)象./proc/slabinfo一個(gè)包含對(duì)slab緩存使用情況統(tǒng)計(jì)的虛擬文件.void*kmem_cache_alloc(kmem_cache_t*cache,intflags);voidkmem_cache_free(kmem_cache_t*cache,constvoid*obj);內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)硬件讀寫(xiě)屏障硬件內(nèi)存屏障.它們請(qǐng)求CPU(和編譯器)來(lái)檢查所有的跨這個(gè)指令的內(nèi)存讀,寫(xiě)#include<asm/system.h>voidrmb(void);voidread_barrier_depends(void);voidwmb(void);voidmb(void);I/O讀寫(xiě)用來(lái)讀和寫(xiě)I/O端口的函數(shù).它們還可以被用戶(hù)空間程序調(diào)用,如果它們有正當(dāng)?shù)臋?quán)限來(lái)存取端口.#include<asm/io.h>unsignedinb(unsignedport);voidoutb(unsignedcharbyte,unsignedport);unsignedinw(unsignedport);voidoutw(unsignedshortword,unsignedport);unsignedinl(unsignedport);voidoutl(unsigneddoubleword,unsignedport);延時(shí)讀寫(xiě)函數(shù)如果在一次I/O操作后需要一個(gè)小延時(shí),你可以使用在前一項(xiàng)中介紹的這些函數(shù)的6個(gè)暫停對(duì)應(yīng)部分;這些暫停函數(shù)以_p結(jié)尾unsignedinb_p(unsignedport);字串函數(shù)這些"字串函數(shù)"被優(yōu)化為傳送數(shù)據(jù)從一個(gè)輸入端口到一個(gè)內(nèi)存區(qū),或者其他的方式.這些傳送通過(guò)讀或?qū)懙酵欢丝赾ount次來(lái)完成.voidinsb(unsignedport,void*addr,unsignedlongcount);voidoutsb(unsignedport,void*addr,unsignedlongcount);voidinsw(unsignedport,void*addr,unsignedlongcount);voidoutsw(unsignedport,void*addr,unsignedlongcount);voidinsl(unsignedport,void*addr,unsignedlongcount);voidoutsl(unsignedport,void*addr,unsignedlongcount);I/O端口資源分配I/O端口的資源分配器.這個(gè)檢查函數(shù)成功返回0并且在錯(cuò)誤時(shí)小于0#include<linux/ioport.h>structresource*request_region(unsignedlongstart,unsignedlonglen,char*name);voidrelease_region(unsignedlongstart,unsignedlonglen);intcheck_region(unsignedlongstart,unsignedlonglen);I/O地址映射ioremap重映射一個(gè)物理地址范圍到處理器的虛擬地址空間,使它對(duì)內(nèi)核可用.iounmap釋放映射當(dāng)不再需要它時(shí).#include<asm/io.h>void*ioremap(unsignedlongphys_addr,unsignedlongsize);void*ioremap_nocache(unsignedlongphys_addr,unsignedlongsize);voidiounmap(void*virt_addr);內(nèi)存區(qū)處理資源分配為內(nèi)存區(qū)處理資源分配的函數(shù)structresource*request_mem_region(unsignedlongstart,unsignedlonglen,char*name);voidrelease_mem_region(unsignedlongstart,unsignedlonglen);intcheck_mem_region(unsignedlongstart,unsignedlonglen);I/O內(nèi)存存取函數(shù)用來(lái)使用I/O內(nèi)存的存取者函數(shù).#include<asm/io.h>unsignedintioread8(void*addr);unsignedintioread16(void*addr);unsignedintioread32(void*addr);voidiowrite8(u8value,void*addr);voidiowrite16(u16value,void*addr);voidiowrite32(u32value,void*addr);

I/O內(nèi)存函數(shù).舊的,類(lèi)型不安全的存取I/O內(nèi)存的函數(shù).unsignedreadb(address);unsignedreadw(address);unsignedreadl(address);voidwriteb(unsignedvalue,address);voidwritew(unsignedvalue,address);voidwritel(unsignedvalue,address);memset_io(address,value,count);memcpy_fromio(dest,source,nbytes);memcpy_toio(dest,source,nbytes);內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)注冊(cè)注銷(xiāo)中斷處理調(diào)用這個(gè)注冊(cè)和注銷(xiāo)一個(gè)中斷處理.#include<linux/interrupt.h>intrequest_irq(unsignedintirq,請(qǐng)求中斷號(hào)irqreturn_t(*handler)(),中斷服務(wù)程序unsignedlongflags,是否共享constchar*dev_name,設(shè)備名稱(chēng)/proc/interrupts來(lái)顯示中斷的擁有者

void*dev_id);用戶(hù)數(shù)據(jù)voidfree_irq(unsignedintirq,void*dev_id);中斷介紹

硬中斷是外部設(shè)備對(duì)CPU的中斷,軟中斷通常是硬中斷服務(wù)程序?qū)?nèi)核的中斷,信號(hào)則是由內(nèi)核(或其他進(jìn)程)對(duì)某個(gè)進(jìn)程的中斷。軟中斷的一種典型應(yīng)用就是所謂的“下半部”(bottomhalf),它的得名來(lái)自于將硬件中斷處理分離成“上半部”和“下半部”兩個(gè)階段的機(jī)制:上半部在屏蔽中斷的上下文中運(yùn)行,用于完成關(guān)鍵性的處理動(dòng)作;而下半部則相對(duì)來(lái)說(shuō)并不是非常緊急的,通常還是比較耗時(shí)的,因此由系統(tǒng)自行安排運(yùn)行時(shí)機(jī),不在中斷服務(wù)上下文中執(zhí)行軟中斷,用軟件方式進(jìn)行模擬,實(shí)現(xiàn)宏觀上的異步執(zhí)行效果。很多情況下,軟中斷和"信號(hào)"有些類(lèi)似

注冊(cè)注銷(xiāo)中斷處理調(diào)用這個(gè)注冊(cè)和注銷(xiāo)一個(gè)中斷處理.#include<linux/interrupt.h>intrequest_irq(unsignedintirq,請(qǐng)求中斷號(hào)irqreturn_t(*handler)(),中斷服務(wù)程序unsignedlongflags,是否共享constchar*dev_name,設(shè)備名稱(chēng)/proc/interrupts來(lái)顯示中斷的擁有者

void*dev_id);用戶(hù)數(shù)據(jù)voidfree_irq(unsignedintirq,void*dev_id);中斷申請(qǐng)標(biāo)志給request_irq的標(biāo)志.SA_INTERRUPT當(dāng)置位了,這表示一個(gè)"快速"中斷處理.快速處理在當(dāng)前處理器上禁止中斷來(lái)執(zhí)行

SA_SHIRQ安裝一個(gè)共享的處理者#include<asm/signal.h>SA_INTERRUPTSA_SHIRQSA_SAMPLE_RANDOM中斷的文件系統(tǒng)節(jié)點(diǎn)報(bào)告硬件中斷和安裝的處理者的文件系統(tǒng)節(jié)點(diǎn).可以獲取當(dāng)前系統(tǒng)得中斷號(hào)和每個(gè)中斷產(chǎn)生的中斷次數(shù)等信息/proc/interrupts/proc/stat驅(qū)動(dòng)使用探測(cè)函數(shù)驅(qū)動(dòng)使用的函數(shù),探測(cè)決定哪個(gè)中斷線被設(shè)備在使用.probe_irq_on這個(gè)函數(shù)返回一個(gè)未安排的中斷的位掩碼.驅(qū)動(dòng)必須保留返回的位掩碼,并且在后面?zhèn)鬟f給probe_irq_off.在這個(gè)調(diào)用之后,驅(qū)動(dòng)應(yīng)當(dāng)安排它的設(shè)備產(chǎn)生至少一次中斷供探測(cè)使用probe_irq_off的返回值是被探測(cè)的中斷號(hào).中斷處理匯編語(yǔ)言文件處理很多機(jī)器級(jí)別的工作.,匯編代碼被安排到每個(gè)可能的中斷.在每個(gè)情況下,這個(gè)代碼將中斷號(hào)壓棧并且跳轉(zhuǎn)到一個(gè)通用段,稱(chēng)為do_IRQ,在irq.c中定義.do_IRQ做的第一件事是確認(rèn)中斷以便中斷控制器能夠繼續(xù)其他事情.它接著獲取給定IRQ號(hào)的一個(gè)自旋鎖,因此阻止任何其他CPU處理這個(gè)IRQ.它清除幾個(gè)狀態(tài)位(包括稱(chēng)為IRQ_WAITING的一個(gè),我們很快會(huì)看到它)并且接著查看這個(gè)特殊IRQ的處理者.如果沒(méi)有處理者,什么不作;自旋鎖釋放,任何掛起的軟件中斷被處理,最后do_IRQ返回.使能和禁止中斷可以使能和禁止中斷。共享處理不使用這個(gè)函數(shù).voiddisable_irq(intirq);voiddisable_irq_nosync(intirq);voidenable_irq(intirq);禁止中斷使用local_irq_save來(lái)禁止本地處理器的中斷并且記住它們之前的狀態(tài)voidlocal_irq_save(unsignedlongflags);voidlocal_irq_restore(unsignedlongflags);使能和禁止中斷在當(dāng)前處理器無(wú)條件禁止和使能中斷的函數(shù).voidlocal_irq_disable(void);voidlocal_irq_enable(void);內(nèi)容提要設(shè)備驅(qū)動(dòng)簡(jiǎn)介建立和運(yùn)行模塊字符驅(qū)動(dòng)調(diào)試技術(shù)并發(fā)和競(jìng)爭(zhēng)高級(jí)字符驅(qū)動(dòng)操作時(shí)間,延時(shí)和延后工作分配內(nèi)存與硬件通訊中斷處理塊設(shè)備驅(qū)動(dòng)塊設(shè)備注冊(cè)register_blkdev注冊(cè)一個(gè)塊驅(qū)動(dòng)到內(nèi)核,并且,可選地,獲得一個(gè)主編號(hào).一個(gè)驅(qū)動(dòng)可被注銷(xiāo),使用unregister_blkdev.#include<linux/fs.h>intregister_blkdev(unsignedintmajor,constchar*name);intunregister_blkdev(unsignedintmajor,constchar*name);塊設(shè)備相關(guān)數(shù)據(jù)結(jié)構(gòu)塊設(shè)備驅(qū)動(dòng)的數(shù)據(jù)結(jié)構(gòu).structblock_device_operations描述內(nèi)核中單個(gè)塊設(shè)備的結(jié)構(gòu).#include<linux/genhd.h>structgendisk;分配gendisk結(jié)構(gòu)的函數(shù),并且返回它們到系統(tǒng).structgendisk*alloc_disk(intminors);voidadd_disk(structgendisk*gd); 塊設(shè)備相關(guān)函數(shù)voidset_capacity(structgendisk*gd,sector_tsectors);存儲(chǔ)設(shè)備能力(以512-字節(jié))在gendisk結(jié)構(gòu)中.voidadd_disk(structgendisk*gd);添加一個(gè)磁盤(pán)到內(nèi)核.一旦調(diào)用這個(gè)函數(shù),你的磁盤(pán)的方法可被內(nèi)核調(diào)用.intcheck_disk_change(structblock_device*bdev);一個(gè)內(nèi)核函數(shù),檢查在給定磁盤(pán)驅(qū)動(dòng)器中的介質(zhì)改變,并且采取要求的清理動(dòng)作當(dāng)檢測(cè)到這樣一個(gè)改變.請(qǐng)求隊(duì)列相關(guān)函數(shù)#include<linux/blkdev.h>request_queue_tblk_init_queue(request_fn_proc*request,spinlock_t*lock);voidblk_cleanup_queue(request_queue_t*);處理塊請(qǐng)求隊(duì)列的創(chuàng)建和刪除的函數(shù).structrequest*elv_next_request(request_queue_t*queue);voidend_request(structrequest*req,intsuccess);elv_next_request從一個(gè)請(qǐng)求隊(duì)列中獲得下一個(gè)請(qǐng)求;end_request可用在每個(gè)簡(jiǎn)單驅(qū)動(dòng)器中來(lái)標(biāo)識(shí)一個(gè)(或部分)請(qǐng)求完成.voidblkdev_dequeue_request(structrequest*req);voidelv_requeue_request(request_queue_t*queue,structrequest*req);從隊(duì)列中除去一個(gè)請(qǐng)求,并且放回它的函數(shù)如果需要.voidblk_stop_queue(request_queue_t*queue);voidblk_start_queue(request_queue_t*queue);如果你需要阻止對(duì)你的請(qǐng)求函數(shù)的進(jìn)一步調(diào)用,調(diào)用blk_stop_queue來(lái)完成.調(diào)用blk_start_queue來(lái)使你的請(qǐng)求方法被再次調(diào)用.請(qǐng)求隊(duì)列參數(shù)控制函數(shù)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論