于PCI9656設備驅動程序的Linu2.6內核研究

時間:2022-11-17 09:45:00

導語:于PCI9656設備驅動程序的Linu2.6內核研究一文來源于網友上傳,不代表本站觀點,若需要原創文章可咨詢客服老師,歡迎參考。

于PCI9656設備驅動程序的Linu2.6內核研究

摘要:本文以64位PCI總線接口芯片pci9656設備驅動程序為基礎,比較了Linux2.6內核與2.4內核的區別,設計與開發了在Linux2.6內核下PCI9656設備驅動程序,進而研究了2.6內核的內存和中斷管理機制。

關鍵字:Linux2.6;設備驅動程序;PCI9656

1引言

Linux操作系統因為其高效、安全、可動態加載及源代碼開放等特點,深受設備驅動程序開發人員的喜愛。系統內核大部分獨立于底層硬件運行,用戶無需關心硬件問題,而用戶操作是通過一組標準化的調用來完成。設備驅動程序的任務是將這些調用映射到作用于實際硬件設備的特定操作上,該編程接口能夠使得驅動程序獨立于內核的其他部分來搭建,在需要時才動態加載到內核。這種模塊化的特點,使得Linux設備驅動程序的編寫過程變得清晰簡單。

目前,為滿足日益龐大的數據處理需要,基于64位PCI總線接口設備的研究開發顯得尤為重要。因而本文將基于PLX公司推出的PCI總線接口芯片PCI9656,設計開發在Linux2.6內核下的設備驅動程序,進而對2.6內核的內存和中斷管理機制進行分析研究。

2Linux2.6與2.4內核的比較

2.1系統穩定性

為了徹底防止對正在被使用的內核模塊進行錯誤操作,2.6內核在加載和導出內核模塊方面都較2.4內核進行了改進,避免了用戶執行將導致系統崩潰的操作,例如強制刪除模塊等。同時,當驅動程序需要在多個文件中包含<linux/module.h>頭文件時,不必定義宏__NO_VERSION__來檢查內核的版本。

2.2統一設備模型

統一設備模型的創建是2.6內核最重要的變化之一。它促進了模塊接口的標準化,其目的是更好地控制和管理設備,主要包括:更準確地確定系統設備,更高效的進行電源管理以及改進的系統總線結構管理。

2.3內核基礎設施

2.6內核為了區別以.o為擴展名的常規對象文件,將內核模塊的擴展名改為.ko。相對于2.4內核下系統所支持的RAM為4GB而言,2.6內核下系統支持更大數量的RAM,在分頁模式下最高可達64GB。同時,2.6內核優化了I/O調度器,確保不會有進程駐留在隊列中過長時間等待輸入/輸出操作,使得I/O操作的響應更為迅速。

2.4外部設備

在2.4內核中有約束大型系統的限制,比如支持的每一類設備的最大數量為256。而2.6內核則徹底地打破了這些限制,可以支持4095種主要的設備類型,每一個單獨的類型又可以支持超過一百萬個的子設備。

3Linux2.6內核下PCI設備驅動程序的設計

3.1PCI設備驅動程序中核心數據結構

在2.6內核下使用file_operations數據結構,來建立設備驅動程序中的函數與主設備號(majornumber)之間的對應關系。該數據結構中包含了指向驅動程序內部大多數函數的指針,描述了虛擬文件系統如何操作一個打開的外圍設備。因而file_operations結構是驅動程序向內核其他部分提供的一個統一的標準設備接口。

file結構是設備驅動程序使用的另一個重要的數據結構,指示當前系統中已打開的文件。它在C語言庫中定義,在調用內核open函數時創建,并傳遞給在該設備上進行操作的所有函數,直到最后的close函數。file結構中還包含了指向它所擁有的file_operations結構的指針。

inode結構由內核自動生成,代表已打開文件的描述符,與每個打開的文件一一對應。它包含了兩個重要的結構成員:dev_t擴展到32位,其中12位主設備號,20位從設備號,而cdev用于存儲一個指向字符設備文件的指針。

3.2驅動程序與內核和外部設備間的關系

(1)通過Linux提供的系統調用函數(例如init_module等)進入內核,這些函數在2.6內核版本下總共有兩百多個,提供了幾乎所有應用程序進入內核所需要執行的操作。

(2)系統的內核函數都有“sys_”前綴(例如函數sys_init_module),應用程序通過訪問設備文件系統來調用這些函數。這一層主要是“devfs”(devicefilesystem)文件管理機制,它是從普通文件和設備文件抽象出來的一個文件系統層,完成進入具體的設備文件操作之前的準備工作。

(3)由設備驅動程序提供具體的函數,來完成對硬件設備的各種操作。特別的對于PCI9656來說,就是通過PCI接口對設備的寄存器和存儲器進行訪問操作,例如調用register_chrdev等函數來初始化芯片內部的狀態寄存器和配置寄存器。

3.3PCI9656芯片的操作流程

PCI總線是目前最常用的外設總線之一,Linux的PCI內核代碼為PCI設備驅動程序的開發提供了強大的支持。PCI9656的驅動程序主要包括以下幾個方面:設備初始化,為PCI芯片分配內存資源,實現數據的讀寫功能,中斷處理,系統收回內存資源,關閉設備等。

4.Linux2.6內核下內存和中斷管理的研究

2.6內核應用了許多新技術來實現對各類外部設備驅動程序的更好支持。下面結合PCI9656驅動程序中的內存和中斷管理,進一步分析和研究2.6內核對內存和中斷進行的改進和優化。

4.1內存管理

在Linux內存管理器中,頁表保持對進程使用的內存物理頁的追蹤,它將虛擬頁映射到物理頁上。系統必須找到映射到該頁的每一個進程,將使用較少的頁置換出去,這樣進程中相應頁的頁表條目才能被更新。隨著在系統中運行的進程數量的增加,將這些頁置換出去的工作量也會急劇增加。

為解決此問題,2.6內核引入了反向映射機制(reversemapping),內存管理器為每一個物理頁建立一個鏈表,包含指向當前映射頁的每個進程的頁表條目(page-tableentry)的指針。該鏈表叫PTE鏈,它極大地提高了找到那些映射某個頁的進程的速度,如圖2所示。驅動程序調用下列內核函數來為PCI9656分配內存空間。

get_free_page(GFP_NOIO,PGD_ORDER);

alloc_pages(gfp_mask,size);

//查找并為PCI9656分配空閑內存物理頁

mempool_alloc(pool,gfp_mask);

request_mem_region(pdx->Pci9656);

remap_page_range(*mem_area,PCI9656,kernel_address,mem_size,prot);

//請求分配內存空間,實現PCI9656物理地址到內存地址的映射

mempool_free(*element,pool);//釋放內存

2.6內核中將頭文件malloc.h改為slab.h,分配標志GFP_BUFFER改為GFP_NOIO和GFP_NOFS,并新增了文件mempool.h。這些變化一起促生了2.6內核中的內存管理器,其設計目標是更高的性能、效率和穩定性。

另一方面,使用反向映射獲得性能的提高也要付出代價,即系統不得不占用一些低端內存來保持對所有反向映射的追蹤,這勢必在32位硬件上成為內存空間的瓶頸。因此2.6內核引入了高端內存頁表(HighmemPTE)機制,讓頁表條目存放在高端內存中,釋放出更多的低端內存區給必須放在這里的內核數據結構。同時,較以前版本的內核而言,2.6內核重新構建了一個更為簡單的內存管理器,提高了整個系統的穩定性。

4.2中斷處理

Linux處理中斷的方式很大程度上與它在用戶空間處理信號的方式一樣,驅動程序只需為設備所對應的中斷注冊一個處理程序,并在中斷到達時進行正確的處理。

在2.4內核之前,Linux系統一直采用cli和sti函數來禁用和啟用中斷,然而對于任意某個例程,想要知道在它被調用時中斷是否被啟用,已變得越來越困難。因而2.6內核定義了函數local_irq_enable和local_irq_disable,用來使能和無效處理器控制的所有中斷,定義函數local_irq_save來將當前中斷的狀態存入flags變量,避免了查詢中斷的狀態信息。

中斷處理程序的作用就是將有關中斷接收的信息反饋給設備,并根據正在服務的中斷的不同含義對數據進行相應的讀或寫。由于PC機只有0-15的中斷號,設備都是以共享的形式申請中斷號,2.6內核改進了PCI設備中斷請求隊列的組織方式,通過設置flags變量中的SA_SHIRQ標志位,并保證內核中所有中斷號(dev_id)的唯一性,來實現中斷的共享。

if(!(inb(card->iobase+CODEC_CMD_INT_STATUS)&0x80000000))return;//識別中斷類型

request_irq(irq,*handler,flags,PCI9656,*dev_id);//向系統注冊PCI9656的中斷

如果中斷注冊成功,則返回值IRQ_RETVAL為0,這時在/proc/interrupts文件中可以看申請成功的中斷。在2.6內核下,request_irq和free_irq從sched.h改到了interrupt.h中定義。

synchronize_irq(irq);//中斷同步

if(wait_event_interruptible(waitqueue,condition)>0)return;//判斷中斷等待使能

outb(intstat&card->iobase+CODEC_CMD_INT_HLDCLR+2);//使能并行端口的中斷報告

//系統響應PCI9656的中斷,執行數據讀寫、寄存器訪問等操作

free_irq(irq,*dev_id);//釋放設備中斷、I/O資源和緩沖區

5實驗與測試

我們設計了Makefile文件和一個簡單的應用程序,在動態加載驅動程序后,對PCI9656開發板進行了大批量數據的讀寫實驗。基于64位PCI總線和100MHz的時鐘頻率,我們對芯片的數據讀寫速率進行了采集,實驗結果統計如圖3所示。

從上圖可以看到,在2.6內核下應用PCI9656作為總線接口芯片,數據的讀寫傳輸速率隨著數據包的大小有大幅度的提高,這在工程應用中有很大的現實意義。

6結束語

本文通過Linux2.6內核所提供的一系列標準函數調用接口,用C++語言開發了PCI9656的設備驅動程序,并在FedoraCore2平臺下調試通過,能正確發送和接收各種大小的數據包。當通信的數據包大小為64KB時,DMA通道的讀寫速度最大可達1.8Gbps,能夠很好的滿足日益龐大的數據處理需要。同時,Linux操作系統源代碼的開放性還能較好的保證數據存儲運算和通信的安全性。

參考文獻

[1]AlessandroRubini&JonathanCorbet,LinuxDeviceDriver(3rdEdtion)[M],USA:O''''Reilly&AssociatesInc,2005