參考來源:http://www.cnblogs.com/lifexy/p/7506277.html
編寫一個最簡單的嵌入式Linux下的驅動程序大致分為以下幾步:
1.編寫驅動函數drive_xxx_open,drive_xxx_write,drive_xxx_read等,這個需要根據實際情況盡心裁剪和添加。
一般情況下,進行設備驅動程序的設計只是比較注重下面的幾個函數:
.llseek = ***_llseek, //文件定位
.read = ***_read, //文件讀取
.write = ***_write, //文件寫入
.ioctl = ***_ioctl, //文件控制
.open = ***_open, //文件打開
.release = ***_release, //文件釋放
本次驅動只做框架,用來打印一些信息即可,所以只填充open,write,read三個函數。
2.函數定義完成以后,對其進行封裝,也就是填入相應的file_operations結構體。
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, //這個成語並不是操作函數,它是一個指向擁有這個結構的模塊的指針,作用是當被使用時阻止模塊被卸載,可以簡單的定位為THIS_MODULE。
.open = first_drv_open, //模塊打開
.write = first_drv_write, //模塊寫
.read = first_drv_read, //模塊度 };
3.驅動模塊加載函數,通過函數 register_chrdev(major, name, &fops) 來
注冊字符設備,定義一個first_drv_init入口 函數來調用這個它。
※register_chrdev函數會把設備添加到Linux系統module結構體的鏈表中。
1:參數分析
* @major: major device number or 0 for dynamic allocation
主設備號,當用戶設置為0時,內核會動態分配一個設備號。
* @name: name of this range of devices
設備名稱
* @fops: file operations associated with this devices
文件系統的接口指針
4.通過module_init()來把入口函數裝入初始化啟動列表中,使內核知道有這個函數存在。
5.寫驅動的first_drv_exit出口函數,調用這個unregister_chrdev()函數卸載模塊,然后通過module_exit()來修飾出口函數。
驅動代碼如下:
#include <linux/module.h> #include <linux/kernel.h> #include <linux/fs.h> #include <linux/init.h> #include <linux/delay.h> #include <asm/irq.h> #include <asm/arch/regs-gpio.h> #include <asm/hardware.h> #include <asm/uaccess.h> #include <asm/io.h> /*1寫出驅動程序first_drv_open first_drv_write */ /* inode結構表示具體的文件,file結構體用來追蹤文件在運行時的狀態信息。*/ static int first_drv_open(struct inode *inode, struct file *file) { printk(“first_drv_open\n”); //打印,在內核中打印只能用printk() return 0; } /*參數filp為目標文件結構體指針,buffer為要寫入文件的信息緩沖區,count為要寫入信息的長度,ppos為當前的偏移位置,這個值通常是用來判斷寫文件是否越界*/ static ssize_t first_drv_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { printk(“first_drv_write\n”); //打印,在內核中打印只能用printk() return 0; } static ssize_t first_drv_read(struct file *file, const char __user *buf, size_t count, loff_t * ppos) { printk(“first_drv_read\n”); //打印,在內核中打印只能用printk() return 0; } /*2定義file_operations結構體來封裝驅動函數first_drv_open first_drv_write */ static struct file_operations first_drv_fops = { .owner = THIS_MODULE, //被使用時阻止模塊被卸載 .open = first_drv_open, .write = first_drv_write, .read = first_drv_read, }; /*4寫first_drv_init入口函數來調用這個register_chrdev()注冊函數*/ int first_drv_init(void) { /*3 register_chrdev注冊字符設備,並設置major=111*/ /*如果設置major為0,表示由內核動態分配主設備號,函數的返回值是主設備號*/ register_chrdev (111, “first_drv”, &first_drv_fops); //111:主設備號,”first_drv”:設備名 /* register_chrdev作用:在VFS虛擬文件系統中找到字符設備,然后通過主設備號找到內核數組里對應的位置,最后將設備名字和fops結構體填進去 */ return 0; } /*5 module_init修飾入口函數*/ module_init(first_drv_init); /*6 寫first_drv_exit出口函數*/ void first_drv_exit(void) { unregister_chrdev (111, “first_drv”); //卸載驅動,只需要主設備號和設備名就行 } /*7 module_exit修飾出口函數*/ module_exit(first_drv_exit); /*8許可證聲明, 描述內核模塊的許可權限,如果不聲明LICENSE,模塊被加載時,將收到內核被污染 (kernel tainted)的警告。*/ MODULE_LICENSE( "GPL v2" );
待續……
