色偷偷偷久久伊人大杳蕉,色爽交视频免费观看,欧美扒开腿做爽爽爽a片,欧美孕交alscan巨交xxx,日日碰狠狠躁久久躁蜜桃

【轉載】塊設備驅動編寫總結一

發(fā)布時間:2009-8-27 22:13    發(fā)布者:原野之狼
關鍵詞: 編寫 , 驅動 , 設備

前一段時間一直在Linux下搞塊設備驅動的開發(fā),實現(xiàn)了多個塊設備模塊,現(xiàn)將塊設備驅動開發(fā)的一些方法總結一下。

 

塊設備與字符設備的區(qū)別

1、  從字面上理解,塊設備和字符設備最大的區(qū)別在于讀寫數(shù)據(jù)的基本單元不同。塊設備讀寫數(shù)據(jù)的基本單元為塊,例如磁盤通常為一個sector,而字符設備的基本單元為字節(jié)。所以Linux中塊設備驅動往往為磁盤設備的驅動,但是由于磁盤設備的IO性能與CPU相比很差,因此,塊設備的數(shù)據(jù)流往往會引入文件系統(tǒng)的Cache機制。

2、 從實現(xiàn)角度來看,Linux為塊設備和字符設備提供了兩套機制。字符設備實現(xiàn)的比較簡單,內(nèi)核例程和用戶態(tài)API一一對應,用戶層的Read函數(shù)直接對應了內(nèi)核中的Read例程,這種映射關系由字符設備的file_operations維護。塊設備接口相對于字符設備復雜,read、write API沒有直接到塊設備層,而是直接到文件系統(tǒng)層,然后再由文件系統(tǒng)層發(fā)起讀寫請求。

 

塊設備讀寫流程

 

在學習塊設備原理的時候,我最關系塊設備的數(shù)據(jù)流程,從應用程序調用Read或者Write開始,數(shù)據(jù)在內(nèi)核中到底是如何流通、處理的呢?然后又如何抵達具體的物理設備的呢?下面對一個帶Cache功能的塊設備數(shù)據(jù)流程進行分析。

 

1、  用戶態(tài)程序通過open()打開指定的塊設備,通過systemcall機制陷入內(nèi)核,執(zhí)行blkdev_open()函數(shù),該函數(shù)注冊到文件系統(tǒng)方法(file_operations)中的open上。在blkdev_open函數(shù)中調用bd_acquire()函數(shù),bd_acquire函數(shù)完成文件系統(tǒng)inode到塊設備bdev的轉換,具體的轉換方法通過hash查找實現(xiàn)。得到具體塊設備的bdev之后,調用do_open()函數(shù)完成設備打開的操作。在do_open函數(shù)中會調用到塊設備驅動注冊的open方法,具體調用如下:gendisk->fops->open(bdev->bd_inode, file)。

2、  用戶程序通過readwrite函數(shù)對設備進行讀寫,文件系統(tǒng)會調用相應的方法,通常會調用如下兩個函數(shù):generic_file_readblkdev_file_write。在讀寫過程中采用了多種策略,首先分析讀過程。

3、 用戶態(tài)調用了read函數(shù),內(nèi)核執(zhí)行generic_file_read,如果不是direct io方式,那么直接調用do_generic_file_read->do_generic_mapping_read()函數(shù),在do_generic_mapping_read(函數(shù)位于filemap.c)函數(shù)中,首先查找數(shù)據(jù)是否命中Cache,如果命中,那么直接將數(shù)據(jù)返回給用戶態(tài);否則通過address_space->a_ops->readpage函數(shù)發(fā)起一個真實的讀請求。在readpage函數(shù)中,構造一個buffer_head,設置bh回調函數(shù)end_buffer_async_read,然后調用submit_bh發(fā)起請求。在submit_bh函數(shù)中,根據(jù)buffer_head構造bio,設置bio的回調函數(shù)end_bio_bh_io_sync,最后通過submit_biobio請求發(fā)送給指定的快設備。

4、  如果用戶態(tài)調用了一個write函數(shù),內(nèi)核執(zhí)行blkdev_file_write函數(shù),如果不是direct io操作方式,那么執(zhí)行buffered write操作過程,直接調用generic_file_buffered_write函數(shù)。Buffered write操作方法會將數(shù)據(jù)直接寫入Cache,并進行Cache的替換操作,在替換操作過程中需要對實際的快設備進行操作,address_space->a_ops提供了塊設備操作的方法。當數(shù)據(jù)被寫入到Cache之后,write函數(shù)就可以返回了,后繼異步寫入的任務絕大部分交給了pdflush daemon(有一部分在替換的時候做了)

5、  數(shù)據(jù)流操作到這一步,我們已經(jīng)很清楚用戶的數(shù)據(jù)是如何到內(nèi)核了。與用戶最接近的方法是file_operations,每種設備類型都定義了這一方法(由于Linux將所有設備都看成是文件,所以為每類設備都定義了文件操作方法,例如,字符設備的操作方法為def_chr_fops,塊設備為def_blk_fops,網(wǎng)絡設備為bad_sock_fops)。每種設備類型底層操作方法是不一樣的,但是通過file_operations方法將設備類型的差異化屏蔽了,這就是Linux能夠將所有設備都理解為文件的緣由。到這里,又提出一個問題:既然這樣,那設備的差異化又該如何體現(xiàn)呢?在文件系統(tǒng)層定義了文件系統(tǒng)訪問設備的方法,該方法就是address_space_operations,文件系統(tǒng)通過該方法可以訪問具體的設備。對于字符設備而言,沒有實現(xiàn)address_space_operations方法,也沒有必要,因為字符設備的接口與文件系統(tǒng)的接口是一樣的,在字符設備open操作的過程中,將inode所指向的file_operations替換成cdev所指向的file_operations就可以了。這樣用戶層讀寫字符設備可以直接調用cdevfile_operations方法了。

6、  截至到步驟(4),讀操作在沒有命中Cache的情況下通過address_space_operations方法中的readpage函數(shù)發(fā)起塊設備讀請求;寫操作在替換Cache或者Pdflush喚醒時發(fā)起塊設備請求。發(fā)起塊設備請求的過程都一樣,首先根據(jù)需求構建bio結構,bio結構中包含了讀寫地址、長度、目的設備、回調函數(shù)等信息。構造完bio之后,通過簡單的submit_bio函數(shù)將請求轉發(fā)給具體的塊設備。從這里可以看出,塊設備接口很簡單,接口方法為submit_bio(更底層函數(shù)為generic_make_request),數(shù)據(jù)結構為struct bio。

7、  submit_bio函數(shù)通過generic_make_request轉發(fā)bio,generic_make_request是一個循環(huán),其通過每個塊設備下注冊的q->make_request_fn函數(shù)與塊設備進行交互。如果訪問的塊設備是一個有queue的設備,那么會將系統(tǒng)的__make_request函數(shù)注冊到q->make_request_fn中;否則塊設備會注冊一個私有的方法。在私有的方法中,由于不存在queue隊列,所以不會處理具體的請求,而是通過修改bio中的方法實現(xiàn)bio的轉發(fā),在私有make_request方法中,往往會返回1,告訴generic_make_request繼續(xù)轉發(fā)比bio。Generic_make_request的執(zhí)行上下文可能有兩種,一種是用戶上下文,另一種為pdflush所在的內(nèi)核線程上下文。

8、 通過generic_make_request的不斷轉發(fā),最后請求一定會到一個存在queue隊列的塊設備上,假設最終的那個塊設備是某個scsi disk/dev/sda)。generic_make_request將請求轉發(fā)給sda時,調用__make_request,該函數(shù)是Linux提供的塊設備請求處理函數(shù)。在該函數(shù)中實現(xiàn)了極其重要的操作,通常所說的IO Schedule就在該函數(shù)中實現(xiàn)。在該函數(shù)中試圖將轉發(fā)過來的bio merge到一個已經(jīng)存在的request中,如果可以合并,那么將新的bio請求掛載到一個已經(jīng)存在request中。如果不能合并,那么分配一個新的request,然后將bio添加到其中。這一切搞定之后,說明通過generic_make_request轉發(fā)的bio已經(jīng)抵達了內(nèi)核的一個站點——request,找到了一個臨時歸宿。此時,還沒有真正啟動物理設備的操作。在__make_request退出之前,會判斷一個bio中的sync標記,如果該標記有效,說明請求的bio是一個是實時性很強的操作,不能在內(nèi)核中停留,因此調用了__generic_unplug_device函數(shù),該函數(shù)將觸發(fā)下一階段的操作;如果該標記無效的話,那么該請求就需要在queue隊列中停留一段時間,等到queue隊列觸發(fā)鬧鐘響了之后,再觸發(fā)下一階段的操作。__make_request函數(shù)返回0,告訴generic_make_request無需再轉發(fā)bio了,bio轉發(fā)結束。

9、  到目前為止,文件系統(tǒng)(pdflush或者address_space_operations)發(fā)下來的bio已經(jīng)mergerequest queue中,如果為sync bio,那么直接調用__generic_unplug_device,否則需要在unplug timer的軟中斷上下文中執(zhí)行q->unplug_fn。后繼request的處理方法應該和具體的物理設備相關,但是在標準的塊設備上如何體現(xiàn)不同物理設備的差異性呢?這種差異性就體現(xiàn)在queue隊列的方法上,不同的物理設備,queue隊列的方法是不一樣的。舉例中的sda是一個scsi設備,在scsi middle levelscsi_request_fn函數(shù)注冊到了queue隊列的request_fn方法上。在q->unplug_fn(具體方法為:generic_unplug_device)函數(shù)中會調用request隊列的具體處理函數(shù)q->request_fn。Ok,到這一步實際上已經(jīng)將塊設備層與scsi總線驅動層聯(lián)系在了一起,他們的接口方法為request_fn(具體函數(shù)為scsi_request_fn)。

10、明白了第(9)點之后,接下來的過程實際上和具體的scsi總線操作相關了。在scsi_request_fn函數(shù)中會掃描request隊列,通過elv_next_request函數(shù)從隊列中獲取一個request。在elv_next_request函數(shù)中通過scsi總線層注冊的q->prep_rq_fnscsi層注冊為scsi_prep_fn)函數(shù)將具體的request轉換成scsi驅動所能認識的scsi command。獲取一個request之后,scsi_request_fn函數(shù)直接調用scsi_dispatch_cmd函數(shù)將scsi command發(fā)送給一個具體的scsi host。到這一步,有一個問題:scsi command具體轉發(fā)給那個scsi host呢?秘密就在于q->queuedata中,在為sda設備分配queue隊列時,已經(jīng)指定了sda塊設備與底層的scsi設備(scsi device)之間的關系,他們的關系是通過request queue維護的。

11、 scsi_dispatch_cmd函數(shù)中,通過scsi host的接口方法queuecommandscsi command發(fā)送給scsi host。通常scsi hostqueuecommand方法會將接收到的scsi command掛到自己維護的隊列中,然后再啟動DMA過程將scsi command中的數(shù)據(jù)發(fā)送給具體的磁盤。DMA完畢之后,DMA控制器中斷CPU,告訴CPU DMA過程結束,并且在中斷上下文中設置DMA結束的中斷下半部。DMA中斷服務程序返回之后觸發(fā)軟中斷,執(zhí)行SCSI中斷下半部。

12、     SCSi中斷下半部中,調用scsi command結束的回調函數(shù),這個函數(shù)往往為scsi_done,在scsi_done函數(shù)調用blk_complete_request函數(shù)結束請求request,每個請求維護了一個bio鏈,所以在結束請求過程中回調每個請求中的bio回調函數(shù),結束具體的bioBio又有文件系統(tǒng)的buffer head生成,所以在結束bio時,回調buffer_head的回調處理函數(shù)bio->bi_end_io(注冊為end_bio_bh_io_sync)。自此,由中斷引發(fā)的一系列回調過程結束,總結一下回調過程如下:scsi_done->end_request->end_bio->end_bufferhead

13、  回調結束之后,文件系統(tǒng)引發(fā)的讀寫操作過程結束。

。。。待續(xù)。。。
本文地址:http://www.54549.cn/thread-3215-1-1.html     【打印本頁】

本站部分文章為轉載或網(wǎng)友發(fā)布,目的在于傳遞和分享信息,并不代表本網(wǎng)贊同其觀點和對其真實性負責;文章版權歸原作者及原出處所有,如涉及作品內(nèi)容、版權和其它問題,我們將根據(jù)著作權人的要求,第一時間更正或刪除。
您需要登錄后才可以發(fā)表評論 登錄 | 立即注冊

相關視頻

關于我們  -  服務條款  -  使用指南  -  站點地圖  -  友情鏈接  -  聯(lián)系我們
電子工程網(wǎng) © 版權所有   京ICP備16069177號 | 京公網(wǎng)安備11010502021702
快速回復 返回頂部 返回列表