摘 要:嵌入式LINUX內核雖小,功能卻十分強大,而且軟件資源較為豐富,在很多領域廣受歡迎。設備驅動程序意義重大,在LINUX內核中占據著重要地位,是實現硬件設備和操作系統交互的關鍵。驅動程序為實現某設備的初始化而編寫相應的初始化函數,當使用該設備時,通過訪問相應的文件節點,編寫過的函數便會提供應有的功能。本文主要分析了字符設備驅動程序。
關鍵詞:嵌入式LINUX;字符設備模型;設備驅動程序
中圖分類號:TP368 文獻標識碼:A 文章編號:1674-7712 (2013) 08-0000-01
一、LINUX系統設備驅動概念
為了將一些硬件細節隱藏,設置統一的編程接口,LINUX系統采用了設備驅動形式,該驅動形式能夠在底層硬件不同的情況下,把具體的設備轉化為抽象的設備文件。設備文件只是驅動訪問的入口點,不會占用系統空間,通過設備文件,系統程序可完成對相關設備的各項操作。在LINUX系統中,主要有三種設備:(1)字符設備;(2)塊設備;(3)網絡設備。
二、設備驅動程序的組成
設備初始化函數是設備驅動程序編寫的重點內容,能夠實現設備的初始化,因此可將設備驅動程序看作是一組函數集合。驅動加載時,需用到入口函數initmodule(),主要負責結構體賦值及寄存器置位等初始化工作,設備注冊是其最主要的工作,由字符設備通過函數register_chrdev()完成注冊。然后此設備便可獲得主設備號和此設備號,同時實現和設備文件的連接。當需要卸載設備驅動時,應將相應的資源進行回收,并將寄存器值復位,同時將該設備注銷。關于系統調用,則主要是對設備的各種操作,包括open、write、read及ioctl等。
可將設備驅動程序分作三部分,一為初始化子程序,主要負責所需硬件設備的檢查工作,確定其是否處于正常狀態。該部分只在初始化時使用;二為請求子程序,作為驅動程序的上半部分,主要是系統調用的結果;三為中斷服務程序,是驅動程序的下半部分。
三、字符設備驅動程序及其注冊卸載
(一)硬件驅動程序被調用時,應用程序只能借助統一的接口函數完成此項工作,而這個接口就是系統調用,每個系統調用都有一個與之相對應的函數。而對字符設備驅動程序而言,所有的函數都集中在一個file_operations類型的數據結構中,并且定義了普通文件I/O函數的入口。至于file_operations,則是在內核的include/linux/fs.h文件中定義。
通常來講,字符設備程序編寫的目的是為了各個具體的file_operations結構編寫相應的函數,而很少會有驅動程序將其全部利用,通常只能利用一部分。字符設備需要的入口包括open(),release(),write(),read(),ioctl()等。其中,open()和ioctl()是本文所需要的。
open()函數,如果系統調用的是設備的特殊文件,需同時調用驅動程序的open()函數:int(*open)(structinode*,structfile);
ioctl()函數,它是一種具有特殊意義的控制函數,借助此函數可將控制信息傳遞給設備,也可以接收來自設備的信息,其原型為:int(*ioctl)(structinode*,structfile*,unsignedint,unsignedlong).
(二)在字符設備進行注冊時,需要依據該函數完成:intregister_chrdev(unsignedintmajor,constchar*name,structfile_operation*fops).當需要卸載時,入口點為cleanup_module函數,卸載函數為:intunregister_chrdev(unsignedintmajor,constchar*name).
四、LED設備程序設計
將設備宏定義為LED設備,其主設備號的代碼如下:
#defineDEVICE_NAME〞leds〞
#defineLED_MAJOR231
s3c2410_leds_fops是一種十分重要的結構,此處的open、ioctl分別被設置為s3c2410_leds_open、s3c2410_leds_ioctl函數,作用依次是對GPIO引腳進行初始化、設置GPIO的輸出電平。
Staticints3c2410_led_open(structinode*inode,structfile*filp)
{
return0;
}
staticints3c2410_led_ioctl(structinode*inode,structfile*filp,unsignedintcmd,unsignedlongarg)
{
switch(cmd){
caseLED_ON:
s3c2410_gpio_setpin(LED1,LED_ON);
dev.status=1;
break;
caseLED_OFF:
s3c2410_gpio_setpin(LED1,LED_OFF);
dev.status=0;
break;
default:
return-EINVAL;
}
return0;
}
Staticstructfileoperationss3c2410_leds_fops={
Owner=THIS_MODULE,
Open=s3c2410_leds_open,
Ioctl=s3c2410_leds_ioctl,
};
在LINUX內核中,驅動程序十分關鍵,需要有相應的初始化函數,對設備進行初始化,通過register_chrdev函數注冊驅動程序,實現LED_MAJOR和s3c2410_leds_fops的連接。當應用程序對主設備號為LED_MAJOR的設備文件進行操作時,就會調用起open、ioctl等函數。
module_init宏和module_exit宏分別可以指定驅動程序初始化函數、卸載函數。
module_init(s3c2410_leds_init);
module_exit(s3c2410_leds_exit).
五、結束語
對LINUX系統的設備驅動程序的概念和組成做了簡單介紹,并結合LED驅動程序的開發對字符設備驅動程序進行了進一步分析。
參考文獻:
[1]王科,姚振東.基于嵌入式Linux的字符設備驅動開發[J].成都信息工程學院學報,2008,24(3):190-191.