版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、設(shè)備驅(qū)動程序(二)1中斷處理中斷的控制:打開和關(guān)閉中斷響應(yīng)函數(shù)的注冊中斷源和中斷號中斷的處理:中斷響應(yīng)函數(shù)使用tasklet2中斷的控制中斷控制器:中斷首先由中斷控制器處理。中斷控制器可以被編程,可以將中斷分派到多處理器環(huán)境下不同的處理器上。cli和sti:用于關(guān)閉和打開中斷,但Linux系統(tǒng)中并不使用這種方式打開和關(guān)閉中斷。unsigned ling flags;.save_flags(flags);cli();/* 這里的代碼在中斷關(guān)閉狀態(tài)下執(zhí)行 */restore_flags(flags);Linux系統(tǒng)中一般使用如下方式關(guān)閉和打開中斷:更安全的方法是使用“鎖機制”,特別是在多處理器環(huán)境
2、下,上述方法不能通過關(guān)閉中斷保護臨界區(qū)代碼。spin_lock_irqsave通過自旋鎖提供鎖機制和對中斷的控制。這種方法也適用于單處理器環(huán)境。3S3C2410的中斷控制器4中斷控制器寄存器操作5中斷源6注冊和注銷中斷響應(yīng)函數(shù)注冊中斷響應(yīng)函數(shù)打開中斷響應(yīng)驅(qū)動程序工作關(guān)閉中斷響應(yīng)注銷中斷響應(yīng)函數(shù)int register_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),unsigned long flags,const char *dev_name,void *dev_id);void free_irq(un
3、signed int irq, void *dev_id);request_irq()/free_irq()unsigned int irq 中斷號,每個中斷響應(yīng)函數(shù)都對應(yīng)一個中斷號。中斷號由使用的硬件決定。void (*handler)(int, void *, struct pt_regs *) 指向中斷響應(yīng)函數(shù)的指針。unsinged long flags 用于中斷控制的變量,實際是一些選項的位掩碼。const char *dev_name 字符串指針。這個字符串將顯示在/proc/interrupts中,表示這個中斷的所有者。void *dev_id 這個指針用于共享的中斷線。這個指針
4、一般由驅(qū)動程序自己使用,指向它自己的私有數(shù) 據(jù)。在中斷不共享時,這個指針可以是空指針,但一般將它指向設(shè)備自己。7flags中的位標志SA_INTERRUPT 當這個比特置位時表示注冊的是一個“快速”中斷,即在中斷響應(yīng)期間中斷是被禁止的。 (相對于“慢速”中斷,因為需要較長的處理時間,系統(tǒng)在處理“慢速”中斷期間中斷是 不被禁止的。這種中斷一般很少被使用。)SA_SHIRQ 這個比特被置位時表示這個中斷可以被其它設(shè)備共享。如果其他設(shè)備已經(jīng)注冊了這個中 斷并且不是共享方式,則無法再注冊這個中斷的中斷響應(yīng)函數(shù)。SA_SAMPLE_RANDOM 這個比特被置位時表示這個中斷可以對熵池做貢獻。熵池是操作系
5、統(tǒng)用于產(chǎn)生真隨機數(shù) 的機制。熵池中的隨機數(shù)經(jīng)常被用來生成用于安全或加密的密碼。如果這個中斷的發(fā)生 是完全隨機的,比如鍵盤中斷,則可以將這個比特置位,向熵池貢獻;否則,比如固定 間隔的時鐘中斷,不包含隨機性,這種中斷就用于為熵池做貢獻。8使用register_irq()注冊一個中斷也是對系統(tǒng)資源申請的一個過程。注冊成功則響應(yīng)的系統(tǒng)資源將被占用。注冊一個中斷可以在驅(qū)動程序初始化的時候,也可以在設(shè)備第一次被打開的時候。一般,中斷的注冊在設(shè)備第一次被打開、同時設(shè)備硬件的中斷功能還沒有被使能時進行。這種方式需要驅(qū)動程序本身對設(shè)備的打開次數(shù)進行管理。int result;result = register
6、_irq(SPIOC_IRQ, spioc_interrupt,SA_INTERRUPT, “spioc”, NULL);if(result) printk(KERN_INFO “spioc: cant get assigned irq %dn”,SPIOC_IRQ);return -1; else enable_irq();我們可以通過/proc界面查看系統(tǒng)上中斷的使用情況:/proc/interrupts/proc/stat9中斷號中斷號是一個中斷最根本的標志,每個中斷源對應(yīng)一個中斷號。中斷號是唯一的,并且是由硬件決定的。我們要使用一個中斷,首先就需要知道它的中斷號。靜態(tài)設(shè)定中斷號:在我們
7、寫驅(qū)動程序時已經(jīng)明確知道要使用的中斷號。驅(qū)動程序模塊加載時設(shè)定中斷號:由用戶在加載驅(qū)動程序時指定要使用的中斷號。比如某些ISA卡通過跳線設(shè)定所使用的中斷,這時用戶可根據(jù)跳線的設(shè)置在加載驅(qū)動程序時指定中斷號,如:insmod ./spioc.o spioc_irq=x自動探測中斷號:由驅(qū)動程序自動決定或由操作系統(tǒng)決定要使用的中斷號。如PCI設(shè)備的中斷號是在系統(tǒng)啟動時由系統(tǒng)分配的。 1 完全由驅(qū)動程序執(zhí)行自動探測:根據(jù)一些設(shè)備的基本知識,驅(qū)動程序可以根據(jù)設(shè)備的某些參數(shù)判斷應(yīng)該使用哪個中斷號。 2 借助內(nèi)核的幫助:內(nèi)核提供了一套底層工具用于探測中斷號unsigned long probe_irq_o
8、n(void);int probe_irq_off(unsigned long);10關(guān)于中斷響應(yīng)函數(shù)中斷響應(yīng)函數(shù)需要滿足如下一些限制: 中斷響應(yīng)函數(shù)不能向用戶空間或從用戶空間傳送數(shù)據(jù),因為中斷并不在進程環(huán)境中執(zhí)行。 中斷響應(yīng)函數(shù)不能做任何與進入睡眠有關(guān)的操作,如調(diào)用sleep_on()等。 中斷響應(yīng)函數(shù)不能使用除GFP_ATOMIC類型之外的內(nèi)存分配功能。 中斷響應(yīng)函數(shù)不能對一個信號量加鎖。 中斷響應(yīng)函數(shù)中不能調(diào)用schedule()函數(shù)進行進程調(diào)度。一般,中斷中斷響應(yīng)函數(shù)完成的工作包括: 從設(shè)備讀數(shù)據(jù),或向設(shè)備寫數(shù)據(jù)。 簡單的數(shù)據(jù)處理或其他簡單操作。 喚醒一個在這個設(shè)備上睡眠的進程。11使
9、用tasklettasklet是Linux中斷處理中bottom-half機制的實現(xiàn)方式之一。在2.3版本的內(nèi)核之前,Linux使用老式的bottom-half實現(xiàn)方式,稱為BH。如果使用的是老版本的內(nèi)核,則無法使用tasklet。tasklet實現(xiàn)了一個中斷處理過程的下半部,因此它也要遵守中斷響應(yīng)函數(shù)應(yīng)該遵守的限制。tasklet在一個中斷的上半部運行完成后才能獲得運行機會,并且由上半部進行調(diào)度。一個tasklet可以被多次調(diào)度,但只運行一次。要使用tasklet,需要首先使用DECLARE_TASKLET宏進行聲明DECLARE_TASKLET(name, function, data);
10、name: tasklet的名字。function: tasklet運行的函數(shù)的名字。它的參數(shù)類型為unsigned long, 返回值類型為void。data: 作為傳遞給function的數(shù)據(jù),是unsigned long類型。然后,在中斷上半部中用tasklet_schedule()來調(diào)度運行一個tasklet。12void spioc_do_tasklet(unsigned long);.DECLARE_TASKLET(spioc_tasklet, spioc_do_tasklet, 0);./* The interrupt handler */void spioc_interrupt
11、(int irq, void *dev_id, struct pt_regs *regs)/* read/write data etc. */.tasklet_schedule(&spioc_tasklet);./* other operations */* The tasklet function */void spioc_do_tasklet(unsigned long somevar)/* Here should do the not so critic but time consumingdata processing */./* If some waiting queue is ne
12、ed to be waked up, do it here */wake_up_interruptible(&spioc_read_queue);13競爭情況由于中斷出現(xiàn)的隨機性,驅(qū)動程序在處理中斷時要特別注意存在競爭條件的情況。避免競爭情況出現(xiàn)所采用的方法充滿了各式各樣的技巧,而且由于競爭情況本身的復(fù)雜性,避免競爭的方法難于全面分類和描述。一般,比較常用的方法有:1. 使用循環(huán)緩沖區(qū),不使用共享變量。2. 使用自旋鎖來實現(xiàn)互斥。3. 使用可以自動增加/減少的鎖變量。由于信號量的使用可能導致一個過程進入睡眠,所以在中斷響應(yīng)函數(shù)中不能使用信號量。關(guān)于競爭情況和處理方法,詳見Linux設(shè)備驅(qū)動程序
13、第九章的相關(guān)內(nèi)容。14驅(qū)動程序的其它內(nèi)容阻塞型輸入輸出:睡眠和喚醒內(nèi)存使用:申請和分配時間控制:延遲和定時使用devfs自動獲得主設(shè)備號驅(qū)動程序調(diào)式技術(shù)安全性15阻塞型輸入輸出當一個進程從設(shè)備讀數(shù)據(jù)但還沒有可用的數(shù)據(jù)時,或向設(shè)備寫數(shù)據(jù)而設(shè)備還沒準備好時,進程一般應(yīng)該進入睡眠。當有可用數(shù)據(jù)或設(shè)備準備就緒時,再通過喚醒的方式將睡眠中的進程喚醒,使得操作可以進行下去。等待隊列及其初始化:wait_queue_head_t spioc_wait_queue;init_waitqueue_head(&spioc_wait_queue);還可以用如下方式聲明一個靜態(tài)的等待隊列:DECLARE_WAIT_Q
14、UEUE_HEAD(spioc_wait_queue);上述語句聲明的等待隊列在編譯時被初始化。16睡眠和喚醒一旦一個等待隊列被聲明和初始化之后,進程就可以使用這個等待隊列進入睡眠。如下函數(shù)用于使一個進程進入睡眠和喚醒一個睡眠中的進程:sleep_on(wait_queue_head_t *queue);interruptible_sleep_on(wait_queue_head_t *queue);sleep_on_timeout(wait_queue_head_t *queue, long timeout);interruptible_sleep_on_timeout(wait_queue
15、_head_t *queue, long timeout);sleep_on(wait_queue_head_t *queue);interruptible_sleep_on(wait_queue_head_t *queue);void wait_event(wait_queue_head_t queue, int condition);int wait_event_interruptible(wait_queue_head_t queue, int condition);wake_up(wait_queue_head_t *queue);wake_up_interruptible(wait_
16、queue_head_t *queue);wake_up_sync(wait_queue_head_t *queue);wake_up_interruptible_sync(wait_queue_head_t *queue);17時間管理:時間間隔、時間延遲Linux操作系統(tǒng)的時鐘產(chǎn)生固定時間間隔的時鐘中斷。時間間隔由HZ值決定。HZ:這是一個與體系結(jié)構(gòu)有關(guān)的值,在大多數(shù)的體系結(jié)構(gòu)上,Linux操作系統(tǒng)定義這個值為100,表示每一秒種的時鐘中斷次數(shù)。jiffies:這個變量是一個操作系統(tǒng)的全局變量。系統(tǒng)啟動時這個變量被初始化成0,并在隨后的每次時鐘中斷時被加1。每次時鐘中斷也被稱為一次“滴答(
17、tick)” 。另外,目前的大多數(shù)CPU都有一個計數(shù)寄存器,專門用于記錄CPU的時鐘脈沖,它每個時鐘周期被加1。這個寄存器記錄的數(shù)據(jù)不受任何CPU其它操作的影響,最真實地記錄了時間的變化。這個寄存器的值可以通過函數(shù)或系統(tǒng)調(diào)用在內(nèi)核空間或用戶空間被讀出使用,如使用void do_gettimeofday(struct timeval *tv);gettimeofday(struct timeval *tv);18時間延遲確定時間間隔的時間延遲:長間隔延遲短間隔延遲任務(wù)的延遲執(zhí)行:任務(wù)隊列(task queue)tasklet內(nèi)核定時器(kernel timer) unsigned ling j
18、= jiffies + delay*HZ while(jiffies j) /* do nothing */; sleep_on_timeout(wait_queue_head_t *q, unsigned long t); interruptible_sleep_on_timeout(); void udelay(unsigned long usecs); void mdelay(unsigned long msecs);19內(nèi)存的申請和分配驅(qū)動程序有時需要動態(tài)申請一些內(nèi)存用于暫存數(shù)據(jù)等。驅(qū)動程序申請的內(nèi)存空間在內(nèi)核地址空間范圍內(nèi),因此它們會被保持在內(nèi)存中而不會被交換到磁盤的交換空間上。驅(qū)動
19、程序用于申請內(nèi)存空間的函數(shù)一般為:void *kmalloc(size_t size, int flags);void kfree(const void *addr);get_free_page(int flags);get_free_pages(int flags, unsigned long order);void free_page(unsigned long addr);void free_pages(unsigned long addr, unsigned long order);size:申請的字節(jié)數(shù)flags:控制內(nèi)存分配的標志參數(shù)GFP_KERNEL:常用的標志,但可能導致進程
20、睡眠,因此不能用于中斷響應(yīng)函數(shù)中。GFP_ATOMIC:不會導致進程睡眠,如果沒有內(nèi)存可用,則內(nèi)存分配失敗。GFP_BUFFER, GFP_USER, GFP_HIGHMEM, _GFP_DMA, _GFP_HIGHMEM按頁面申請內(nèi)存空間。flags與kmalloc中的含義相同,order為以2為底的指數(shù),如order=3表示申請8個頁面。void *vmalloc(unsigned long size);void vfree(void *addr);void *ioremap(unsigned long offset, unsigned long size);void iounmap(vo
21、id *addr);用于在虛擬地址空間中申請內(nèi)存空間。20使用devfs2.4版本Linux提供了對Device 的支持。使用devfs可以在設(shè)備驅(qū)動程序初始化時自動在/dev目錄中創(chuàng)建相應(yīng)的設(shè)備文件,并在設(shè)備驅(qū)動程序注銷時自動移除相應(yīng)的設(shè)備文件。使用devfs要求內(nèi)核編譯時定義了符號CONFIG_DEVFS_FSdevfs_handle_t devfs_register(devfs_handle_t dir, const char *name, unsigned int flags, unsigned int major, unsigned int minor, umode_t mode,
22、void *ops, void *info);void devfs_unregister(devfs_handle_t deventry);這兩個函數(shù)用于向文件系統(tǒng)添加和移除設(shè)備文件int devfs_register_chrdev(unsigned int major, const char *name, struct fops);int devfs_unregister_chrdev(unsigned int major, const char *name);這兩個函數(shù)用于向內(nèi)核注冊和撤消一個字符設(shè)備21設(shè)備號的動態(tài)分配雖然每個設(shè)備都有一個設(shè)備號(實際包括主設(shè)備號和次設(shè)備號),但是當文件系
23、統(tǒng)建立之后,我們使用的是設(shè)備的文件名,并不直接使用設(shè)備號。因此從應(yīng)用的角度看,一個設(shè)備被分配哪個設(shè)備號并不重要。Linux操作系統(tǒng)提供了設(shè)備號的動態(tài)分配機制。 int result; . result = register_chrdev(spioc_major, “spioc”, &spioc_fops); if(result 0) printk(KERN_WARNING “spioc: cant get major %dn”, spioc_major);return result; if(spioc_major = 0)spioc_major = result; . unregister_c
24、hrdev(spioc_major, “spioc”);上述方法同樣適用于devfs_register_chrdev()函數(shù)。22驅(qū)動程序的調(diào)試使用printk(): printk(KERN_DEBUG “some messages here with variable %d.n”, value);共有8個記錄級別(loglevel): KERN_EMERG, KERN_ALERT, KERN_CRIT, KERN_ERR, KERN_WARNING, KERN_NOTICE, KERN_INFO, KERN_DEBUG使用/proc文件系統(tǒng): /proc文件系統(tǒng)是一個特殊的由軟件建立的文件系
25、統(tǒng),內(nèi)核利用它導出信息。/proc下的每個文件都與內(nèi)核的一個功能/函數(shù)相聯(lián)系,當用戶讀取相應(yīng)的文件時,這些功能/函數(shù)的信息就被輸出了。使用/proc文件系統(tǒng)主要用于查詢一些內(nèi)核信息。 cat /proc/modules使用測試程序: 利用用戶級的應(yīng)用程序測試驅(qū)動程序,對驅(qū)動程序的運行進行觀察。使用系統(tǒng)出錯記錄: 使用系統(tǒng)出錯轉(zhuǎn)儲(dump)信息。使用gdb: 使用gdb可以對運行中的內(nèi)核進行有限調(diào)試,主要是讀取一些內(nèi)核信息。使用kdb: 第三方提供的一個內(nèi)核調(diào)試器()。使用kdb需要給內(nèi)核打上相應(yīng)的補丁,并重新編譯和安裝內(nèi)核。目前kdb對不同體系結(jié)構(gòu)的支持非常有限。23安全性安全性是操作系統(tǒng)非
26、常重要的一個方面,也是一個非常復(fù)雜的課題。驅(qū)動程序因為是作為內(nèi)核的一部分而工作,所以驅(qū)動程序的安全性和內(nèi)核的安全性同等重要,因而也是整個操作系統(tǒng)的安全性。對設(shè)備使用的控制:設(shè)備文件的使用;只能單次打開的設(shè)備;只能由一個用戶打開的設(shè)備;.驅(qū)動程序內(nèi)部數(shù)據(jù)的使用:對數(shù)據(jù)邊界的檢測;內(nèi)存泄露;緩沖區(qū)溢出;內(nèi)存空間的初始化;.驅(qū)動程序結(jié)構(gòu)的合理性:中斷的處理;競爭條件的避免;對錯誤的細致處理;.驅(qū)動程序代碼的可重入性(reentrant code):狀態(tài)變量和私有數(shù)據(jù)的處理。24實例:在spioc中使用中斷和devfs中斷源:鍵盤中斷使用方式:數(shù)據(jù)的讀(或?qū)懀┯芍袛嗫刂茍?zhí)行tasklet的使用使用de
27、vfs25NET-ARM2410開發(fā)板鍵盤電路原理圖鍵盤產(chǎn)生的中斷,使用S3C2410外部中斷 EINT4IIC接口鍵盤及LED控制器26中斷號我們使用的中斷源是s3c2410的一個外部中斷信號線,EINT4,它的中斷號是固定的。在include/asm-arm/arch-s3c2410/目錄下的hardware.h和irqs.h中有關(guān)于s3c2410的各種寄存器以及各種資源,如地址、中斷號等的定義。為了使用這些量,我們要在引用頭文件時包含這兩個頭文件,如下所示:#include #include .#define NORMAL_IRQ_OFFSET32#define IRQ_EINT4(0
28、+NORMAL_IRQ_OFFSET)#define IRQ_EINT5(1 +NORMAL_IRQ_OFFSET).在include/asm-arm/arch-s3c2410/irqs.h中有如下定義27中斷響應(yīng)函數(shù)我們使用的中斷源是s3c2410的一個外部中斷信號線,EINT4,它的中斷號是固定的。在include/asm-arm/arch-s3c2410/目錄下的hardware.h和irqs.h中有關(guān)于s3c2410的各種寄存器以及各種資源,如地址、中斷號等的定義。為了使用這些量,我們要在引用頭文件時包含這兩個頭文件,如下所示:#include #include 中斷響應(yīng)函數(shù)stati
29、c void spioc_interrupt(int irq, void *dev_id, struct pt_regs *regs)printk(kbd interrupt received.n);/* do something, such read/write data to I/O port */* left other things to tasklet */tasklet_schedule(&spioc_tasklet);return;28tasklet初始化taskletstatic void spioc_do_tasklet(unsigned long);DECLARE_TASK
30、LET(spioc_tasklet, spioc_do_tasklet, 0);taskletstatic void spioc_do_tasklet(unsigned long)/* do some data process here */int i;for(i=0; i count)cnt = count;copy_to_user(buf, rbuff, cnt);return cnt;假設(shè)“讀”操作是中斷驅(qū)動的,則讀函數(shù)應(yīng)該在等待隊列上“睡眠”,直到中斷的到來。30注冊中斷響應(yīng)函數(shù)如果這個中斷信號只由我們這個驅(qū)動程序模塊單獨使用,則我們可以在驅(qū)動程序初始化階段注冊中斷響應(yīng)函數(shù)。我們以不共
31、享的方式使用這個中斷。static int _init spioc_init(void)int result;.result = request_irq(_IRQ_EINT4, spioc_interrupt, SA_INTERRUPT, spioc, NULL);if(result) printk(spioc: irq request failed.n);/* some furthertreatment for this case */.31初始化中斷控制器和打開/關(guān)閉中斷中斷控制器的初始化應(yīng)該在操作系統(tǒng)啟動階段的中斷初始化階段完成了。操作系統(tǒng)的移植者已經(jīng)幫我們完成了這個工作。然而,對某些微
32、控制器,它的管腳可能是復(fù)用的,而缺省狀態(tài)又不是作為中斷輸入引腳,這時如果打開中斷,可能造成系統(tǒng)“死掉”,比如電平響應(yīng)的中斷,將不停地執(zhí)行中斷響應(yīng)程序,導致系統(tǒng)其它代碼沒有機會運行。static int spioc_open(.).enable_irq(IRQ_EINT4);.static int spioc_close(.).disable_irq(IRQ_EINT4);.32使用devfs注意,是否能使用devfs與內(nèi)核是否支持這個特性相關(guān)。內(nèi)核在編譯時應(yīng)該設(shè)定CONFIG_DEVFS_FS符號。我們還可以使用動態(tài)獲得的設(shè)備號。#include static devfs_handle_t d
33、evfs_spioc;static int _init spioc_init(.)int result;.result = devfs_register_chrdev(0, &spioc_fops);if(result 0) return result;spioc_major = result;devfs_spioc = devfs_register(NULL, spioc, DEVFS_FL_DEFAULT, spioc_major, 0, S_IFCHR | S_IRUSR | S_IWUSR, &spioc_fops, NULL);.static void _exit spioc_exi
34、t(void).devfs_unregister(devfs_spioc);devfs_unregister_chrdev(spioc_major, spioc);.33塊設(shè)備塊設(shè)備基本概念:塊操作為基礎(chǔ),速度是主要考慮因素,類型復(fù)雜。與字符設(shè)備相似之處:注冊/撤消,設(shè)備號,block_device_operations。塊設(shè)備的基本操作塊設(shè)備的讀寫:request。其它特性:如可移動性,分區(qū)等。塊設(shè)備的加載和卸載:文件系統(tǒng)。34面向塊數(shù)據(jù)的操作,數(shù)據(jù)塊的大小主要由經(jīng)驗值來確定,一般為2的整數(shù)冪次字節(jié)大小,如4kB, 16kB等。塊設(shè)備是用于存儲大量數(shù)據(jù)的設(shè)備,主要是各種數(shù)據(jù)存儲介質(zhì)設(shè)備,如硬
35、盤,軟盤,光盤,以及U盤等。出于效率的要求,塊設(shè)備的數(shù)據(jù)傳輸幾乎都使用較大的緩沖區(qū),并使用請求隊列。塊設(shè)備主要由文件系統(tǒng)使用,因此,塊設(shè)備上幾乎都要建立文件系統(tǒng),要有磁盤分區(qū)。應(yīng)用幾乎不直接使用塊設(shè)備,而是通過文件系統(tǒng)使用塊設(shè)備,如各種應(yīng)用程序從磁盤的文件中讀數(shù)據(jù)和向磁盤文件寫入數(shù)據(jù)。塊設(shè)備的操作要比字符設(shè)備復(fù)雜許多,如磁盤電機的啟動/停止操作,磁盤壞塊的處理等。塊設(shè)備在在/dev目錄下有相應(yīng)的設(shè)備文件,有主設(shè)備號和次設(shè)備號。每個磁盤有一個主設(shè)備號,一個磁盤上得不同分區(qū)使用不同的次設(shè)備號。速度和效率是塊設(shè)備要考慮的主要因素,為提高效率,塊設(shè)備驅(qū)動程序一般都實現(xiàn)一定程度的預(yù)讀功能。由于使用了緩沖
36、區(qū),磁盤中的數(shù)據(jù)需要經(jīng)常與系統(tǒng)緩沖的數(shù)據(jù)保持同步。否則會導致文件系統(tǒng)崩潰。塊設(shè)備基本概念35塊設(shè)備的注冊和注銷#inclide int register_blkdev(unsigned int major, const char *name,struct block_device_operations *bdops);int unregister blkdev(unsigned int major, const char *name);struct block_device_operations int (*open)(struct inode *inode, struct file *fil
37、p); int (*release)(struct inode *inode, struct file *filp); int (*ioctl)(struct inode *inode, struct file *filp,unsigned command, unsigned long arg); int (*check_media_change)(kdev_t dev); int (*revalidate)(kdev_t dev);#include extern void register_disk(struct gendisk *dev, kdev_t first, unsigned mi
38、nors, struct block_device_operations *ops, long size);36塊設(shè)備的打開和關(guān)閉用戶的程序一般只打開和關(guān)閉磁盤上的文件,并不打開塊設(shè)備本身。例外的情況是使用如fdisk一類的應(yīng)用程序?qū)Υ疟P進行分區(qū)、使用mount命令加載一個文件系統(tǒng)等。這些程序?qū)?zhí)行塊設(shè)備文件的打開/關(guān)閉操作。fdisk /dev/hdamke2fs /dev/hda3mount -t ext2 /dev/hda3 /my_mount_pointumount /my_mount_point37塊設(shè)備的讀寫#inclide blk_init_queue(request_queue
39、_t *queue, request_fn_proc *request);blk_cleanup_queue(request_queue_t *queue);void request(request_queue_t *queue);每當文件系統(tǒng)想想磁盤寫入數(shù)據(jù)或打算從磁盤讀出數(shù)據(jù)時,它就調(diào)用驅(qū)動程序的rerquest函數(shù),將讀寫請求放到一個請求隊列中去。這是一個需要由驅(qū)動程序開發(fā)者完成的函數(shù)。這個函數(shù)的主要結(jié)構(gòu)是一個無限的循環(huán),不停地檢查等待隊列,處理等待隊列中的請求。被放到等待隊列中的元素是request struct類型的結(jié)構(gòu)體。block_device_operations中沒有read
40、和write這兩個函數(shù)。實際塊設(shè)備的讀寫不是使用read/write完成的。出于效率的考慮,塊設(shè)備的讀寫使用了請求隊列。3839可移動設(shè)備塊設(shè)備驅(qū)動程序需要處理可移動介質(zhì)的情況,如軟盤、U盤等。struct block_device_operations int (*open)(struct inode *inode, struct file *filp); int (*release)(struct inode *inode, struct file *filp); int (*ioctl)(struct inode *inode, struct file *filp,unsigned command, unsigned long arg); int (*check_media_change)(kdev_t dev); int (*revalidate)(kdev_t dev);塊設(shè)備驅(qū)動程序提供兩個函數(shù)用于檢測介質(zhì)改變的情況以及介質(zhì)改變后重新使之可用:check_media_change(kd
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 粉狀化妝品制造工安全生產(chǎn)能力考核試卷含答案
- 快件派送員安全培訓水平考核試卷含答案
- 硫酸生產(chǎn)工崗前師帶徒考核試卷含答案
- 冷拉絲工改進能力考核試卷含答案
- 侍酒師改進水平考核試卷含答案
- 樹樁盆景工安全生產(chǎn)知識強化考核試卷含答案
- 金屬材管拉拔工標準化測試考核試卷含答案
- 2025年云南城市建設(shè)職業(yè)學院馬克思主義基本原理概論期末考試模擬題附答案
- 2024年西疇縣事業(yè)單位聯(lián)考招聘考試真題匯編附答案
- 2024年海南州特崗教師招聘考試真題題庫附答案
- 2026年1月福建廈門市集美區(qū)后溪鎮(zhèn)衛(wèi)生院補充編外人員招聘16人筆試備考題庫及答案解析
- 2025 年大學人工智能(AI 應(yīng)用)期中測試卷
- 重慶市渝中區(qū)(2025年)輔警協(xié)警筆試筆試真題(附答案)
- 暴雪車輛行駛安全培訓課件
- 2026年七臺河職業(yè)學院單招綜合素質(zhì)筆試模擬試題帶答案解析
- 2026年吉林司法警官職業(yè)學院單招職業(yè)技能考試備考試題帶答案解析
- 2025內(nèi)蒙古潤蒙能源有限公司招聘22人考試題庫附答案解析(奪冠)
- 2026年國家電網(wǎng)招聘之電網(wǎng)計算機考試題庫500道有答案
- 年味課件教學課件
- 中國臨床腫瘤學會(csco)胃癌診療指南2025
- 廣東省廣州市2025年上學期八年級數(shù)學期末考試試卷附答案
評論
0/150
提交評論