Linux驅動必須先由module_init ( function_name)函數載入驅動,由module_exit (function_name )函數卸載驅動,其中function_name分別為初始化函數和清除裝置的函數。
要建立一個裝置,得使用dev_t devno = MKDEV(DL402_MAJOR, 0)擷取裝置號,其中DL402_MAJOR是介面板的主裝置號,再使用函數register_chrdev_region向系統註冊字元驅動,register_chrdev_region函數定義為:
int register_chrdev_region(dev_tfirst, unsigned int count, char *name);
其中第一個參數是要註冊的裝置號,第二個參數是要註冊裝置的個數,第三個是要註冊裝置的裝置名稱。
註冊字元裝置後,用request_region(unsigned longfirst, unsigned long n, const char *name) 函數向核心申請n個I/O連接埠,這些連接埠從first開始,name參數為裝置的名稱,成功返回非NULL。申請了個I/O連接埠後,便該申請一個中斷介面。
使用request_irq(unsigned int irq, irqreturn_t(*handler), unsigned long flags, const char *dev_name, void *dev_id)函數向核心申請中斷介面,其中參數irq表示所要申請的硬體中斷號;handler為向系統登記的中斷處理子程式名;flags是申請時的選項,它決定中斷處理常式的一些特性dev_name為裝置名稱,將會出現在/proc/interrupts檔案裡。如果中斷由某個處理常式獨佔,則dev_id可以為NULL。request_irq返回0表示成功,返回-INVAL表示irq>15或handler==NULL,返回-EBUSY表示中斷已經被佔用且不能共用。若申請失敗同樣取消之前的步驟。在卸載模組時需釋放中斷使用void free_irq(unsigned int irq,void *dev_id)。
初始化字元裝置和載入字元裝置,使用裝置需要一系列函數,這些函數需要包含到結構體file_operations中,其中包含讀、開啟以及中斷處理的函數,定義函數void read(void)、void open(void)、voidioctl(void),以及結構體:
static const struct file_operations fops = {
.owner = THIS_MODULE,
.read = read,
.open = open,
.unlocked_ioctl = ioctl,
};
之後,方可初始化、載入字元裝置:
cdev_init(dev, &fops);
ret = cdev_add(dev, devno, 1);
cdev_add函數返回0則成功,檢測其是否成功只需要檢測ret是否為0,失敗需要釋放連接埠裝置號、申請的記憶體以及申請的I/O連接埠號碼:
free_irq(0,dev);
unregister_chrdev_region(devno, 1);
release_region(0, 1);
kfree(dev);
return ret;
至此,初始化的程式以及完成,還需要卸載驅動的程式,建立函數void exit(void)為卸載驅動的函數,其中應包含釋放裝置號、申請的I/O連接埠、釋放中斷介面:
free_irq(0, dev);
free_irq(0, NULL);
release_region(0, 1);
kfree(dev);
最後需要動態載入初始化驅動的函數以及卸載驅動的函數:
module_init(init);
module_exit(exit);
編譯、執行後,在shell介面上執行命令”lsmod”,在Module欄下看到你的裝置名稱則成功,安裝以上來寫的程式,應該看到“Test”。若要卸載裝置,只需要在shell介面上執行命令”remod 裝置名稱”即可。