zoukankan      html  css  js  c++  java
  • 嵌入式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
    ”);      //打印,在内核中打印只能用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
    ”);      //打印,在内核中打印只能用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
    ”);      //打印,在内核中打印只能用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" );

      待续……

  • 相关阅读:
    P4049 [JSOI2007]合金
    CF1073C Vasya and Robot
    输出100以内奇数,偶数,质数,合数的脚本
    取/etc/password文件最后一个单词的最后一个字符
    window下进程退出后自动重启
    如何让DOS命令在新窗口打开
    dos命令关闭所有dos窗口
    使用jps查看JVM进程信息
    windows .bat批处理实现进程监控确保程序运行
    经典博客4(六尺帐篷)
  • 原文地址:https://www.cnblogs.com/han-bing/p/8807602.html
Copyright © 2011-2022 走看看