嵌入式Linux-驅動程序編寫框架


參考來源: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" );

 

 

  待續……

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM