zoukankan      html  css  js  c++  java
  • Android中字符设备驱动和应用实例(一) 驱动部分

    Android中字符设备驱动和应用实例(一)——驱动部分

    下面介绍创建Android设备对应的字符设备驱动

    1 字符驱动

    在此示例中,我们将字符驱动添加到drivers/char目录下。

    (1)字符驱动的路径如下:

    drivers/char/class_reg_unreg.c

    (2)字符驱动的内容如下:

      1 #include <linux/module.h>
      2 #include <linux/init.h>
      3 #include <linux/kernel.h>
      4 #include <linux/slab.h>
      5 #include <linux/vmalloc.h>
      6 #include <linux/fs.h>
      7 #include <linux/cdev.h>
      8 #include <asm/uaccess.h>
      9 #include <linux/types.h>
     10 #include <linux/moduleparam.h>
     11 #include <linux/pci.h>
     12 #include <asm/unistd.h>
     13 #include <linux/device.h>
     14 
     15 
     16 #define    MEM_MALLOC_SIZE    4096
     17 #define    MEM_MAJOR        246
     18 #define    MEM_MINOR        0
     19 
     20 static char *mem_spvm;
     21 static struct class *mem_class;
     22 static struct cdev *mem_cdev;
     23 static int devno; 
     24 
     25 static int __init class_reg_unreg_init(void);
     26 static void __exit class_reg_unreg_exit(void);
     27 static int mem_open (struct inode *inode, struct file *filp);
     28 static int mem_release (struct inode *inode, struct file *filp);
     29 static ssize_t mem_read (struct file *filp, char __user *buf, size_t count, loff_t *f_pos);
     30 static ssize_t mem_write (struct file *filp, const char __user *buf, size_t count, loff_t *f_pos);
     31 
     32 static void class_create_release (struct class *cls);
     33 
     34 static void class_create_release (struct class *cls)
     35 {
     36     printk("%s\n", __func__ );
     37     kfree(cls);
     38 }
     39 
     40 struct file_operations mem_fops = 
     41 {
     42     .open = mem_open,
     43     .release = mem_release,
     44     .read = mem_read,
     45     .write = mem_write,
     46 };
     47 
     48 
     49 int mem_open (struct inode *inode, struct file *filp)
     50 {
     51     printk("mem open\n" );
     52     // 模块引用计数器子加
     53     try_module_get(THIS_MODULE);
     54     return 0;
     55 }
     56 
     57 int mem_release (struct inode *inode, struct file *filp)
     58 {
     59     printk("%s\n", __func__);
     60     // 模块引用计数器子加
     61     module_put(THIS_MODULE);
     62     return 0;
     63 }
     64 
     65 ssize_t mem_read (struct file *filp, char __user *buf, size_t count,
     66                         loff_t *f_pos)
     67 {
     68     int res = -1;
     69     char *tmp;
     70 
     71     printk("%s\n", __func__);
     72     
     73     tmp = mem_spvm;
     74     if (tmp == NULL) 
     75     {
     76         return 0;
     77         printk("%s error: empty pointer!\n", __func__);
     78     }
     79 
     80     if (count > MEM_MALLOC_SIZE)
     81     {
     82         count = MEM_MALLOC_SIZE;
     83         printk("%s size too large, resize to max size\n", __func__);
     84     }
     85     
     86     res = copy_to_user(buf, tmp, count);
     87     if (res == 0)
     88     {
     89         printk("<0> copy to user data success\n");
     90         return count;
     91     }
     92     printk("<0> copy to user data failed: res=%d\n", res);
     93 
     94     return 0;
     95 }
     96 
     97 ssize_t mem_write (struct file *filp, const char __user *buf, size_t count,
     98                         loff_t *f_pos)
     99 {
    100     int res = -1;
    101     char *tmp;
    102 
    103     printk("%s\n", __func__);
    104 
    105     tmp = mem_spvm;
    106     if (tmp == NULL) 
    107     {
    108         return 0;
    109         printk("%s error: empty pointer!\n", __func__);
    110     }
    111 
    112     if (count > MEM_MALLOC_SIZE)
    113     {
    114         count = MEM_MALLOC_SIZE;
    115         printk("%s size too large, resize to max size\n", __func__);
    116     }
    117 
    118     res = copy_from_user(tmp, buf, count);
    119     if (res == 0)
    120     {
    121         printk("<0> copy from user data success\n");
    122         return count;
    123     }
    124     printk("<0> copy from user data fail: res=%d\n", res);
    125 
    126     return 0;
    127 }
    128 
    129 
    130 static int __init class_reg_unreg_init(void)
    131 {
    132     int ret = 0;
    133 
    134     printk("%s\n", __func__);
    135 
    136     // 创建设备号
    137     devno = MKDEV(MEM_MAJOR, MEM_MINOR);
    138 
    139     // 申请字符设备号,并创建字符设备节点
    140     if (MEM_MAJOR)
    141     {
    142         // 静态申请设备号
    143         ret = register_chrdev_region(devno, 1, "my_char_dev");
    144     }
    145     else
    146        {
    147            // 动态分配设备号
    148         ret = alloc_chrdev_region(&devno, 0, 1, "my_char_dev");
    149     }  
    150     if (ret) 
    151     {
    152         printk("<0> register chrdev failed!\n");
    153         goto fail_register;    
    154     }
    155     printk("<0>register chrdev success, major, minor= (%d, %d)\n", MAJOR(devno), MINOR(devno));
    156 
    157     // 分配缓冲区
    158     mem_spvm = (char *)vmalloc(MEM_MALLOC_SIZE);
    159     if (mem_spvm == NULL)
    160     {
    161         ret = 1;
    162         printk("<0>vmalloc failed!\n");
    163         goto fail_vmalloc;
    164     }
    165     printk("<0>vmalloc success, addr=0x%x\n", (unsigned int)mem_spvm);
    166 
    167     // 动态分配一个字符设备对象
    168     mem_cdev = cdev_alloc();
    169     if (mem_cdev == NULL) 
    170     {
    171         printk("<0> cdev_alloc failed!\n");
    172         ret = 1;
    173         goto fail_cdev_alloc;
    174     } 
    175     printk("<0> cdev_alloc success, addr=0x%x\n", (unsigned int)mem_cdev);
    176 
    177     // 初始化字符设备对象
    178     cdev_init(mem_cdev, &mem_fops);
    179     // 初始化字符设备持有者
    180     mem_cdev->owner = THIS_MODULE;
    181     // 将字符设备添加到内核系统中
    182     ret = cdev_add(mem_cdev, devno, 1);
    183     if (ret) 
    184     {
    185         printk("<0> cdev_add failed!\n");
    186         goto fail_cdev_add;    
    187     }
    188 
    189     // 申请class结构体内存
    190     mem_class = kzalloc(sizeof(*mem_class), GFP_KERNEL);
    191     if (mem_class == NULL) 
    192     {
    193         printk("<0> create mem class failed!\n");
    194         ret = 1;
    195         goto fail_mem_class;
    196     }
    197     printk("<0> create mem class success\n");
    198 
    199     mem_class->name = "my_char_dev";
    200     mem_class->owner = THIS_MODULE;
    201     // 注销时class时的回调函数,在此回调函数中释放之前所分配的class结构体内存
    202     mem_class->class_release = class_create_release;
    203 
    204     // 将class注册到内核中,同时会在/sys/class/下创建class对应的节点
    205     int retval = class_register(mem_class);
    206     if (ret) 
    207     {
    208         printk("<0> class_register failed!\n");
    209         goto fail_class_reg;    
    210     }
    211     printk("<0> class_register success\n");
    212 
    213     // 在/dev/下创建与class对应的设备节点
    214     device_create(mem_class, NULL, devno, NULL, "my_char_dev");
    215 
    216     return 0;
    217 
    218 fail_class_reg:
    219 
    220 fail_mem_class:
    221     if (mem_class)
    222     {
    223         kfree(mem_class);
    224         mem_class = NULL;
    225     }
    226 
    227 fail_cdev_add:
    228 fail_cdev_alloc:
    229     if (mem_cdev)
    230     {
    231         kfree(mem_cdev);
    232         mem_cdev = NULL;
    233     }
    234 
    235 fail_vmalloc:
    236     if (mem_spvm)
    237     {
    238         vfree(mem_spvm);
    239         mem_spvm = NULL;
    240     }
    241 
    242 fail_register:
    243     unregister_chrdev_region(devno, 1);
    244 
    245     return ret;
    246 }
    247 
    248 static void __exit class_reg_unreg_exit(void)
    249 {
    250     printk("%s\n", __func__);
    251     device_destroy(mem_class, devno);
    252     if (mem_class)
    253     {
    254         class_unregister(mem_class);
    255         //kfree(mem_class);
    256         mem_class = NULL;
    257     }
    258 
    259     if (mem_spvm)
    260     {
    261         vfree(mem_spvm);
    262         mem_spvm = NULL;
    263     }
    264 
    265     if (mem_cdev)
    266     {
    267         // 从内核中将设备删除
    268         cdev_del(mem_cdev);
    269         kfree(mem_cdev);
    270         mem_cdev = NULL;
    271     }
    272 
    273     // 注销字符设备
    274     unregister_chrdev_region(devno, 1);
    275 }
    276 
    277 module_init(class_reg_unreg_init);
    278 module_exit(class_reg_unreg_exit);
    279 
    280 MODULE_AUTHOR("skywang <wangkuiwu@gmail.com>");
    281 MODULE_DESCRIPTION("class register unregister driver");
    282 MODULE_LICENSE("GPL");
    View Code

      

    2 修改配置

    (1)修改drivers/char/Kconfig,添加以下内容:

    config SKYWANG_CLASS_REG_UNREG
         tristate "skywang class register and unregister driver"
         help
         add this to support skywang class register and unregister driver 

    (2)修改drivers/char/Makefile,添加以下内容:

    +obj-$(CONFIG_SKYWANG_CLASS_REG_UNREG) += class_reg_unreg.o 

    3 编译

    (1)执行make menuconfig生产字符设备模块文件,如下图:

    (2)执行make编译生成模块文件,模块文件路径如下:

    drivers/char/ class_reg_unreg.ko

    4 装载/卸载到手机中

    (1)将class_reg_unreg.ko导入到Android系统中,执行以下命令:

    # adb push class_reg_unreg.ko /system/class_reg_unreg.ko

    (2)装载模块文件,执行以下命令:

    # cd /system/
    # insmod class_reg_unreg.ko

    执行insmod之后,坚持是否生成文件节点“/sys/class/my_char_dev”和“/dev/my_char_dev”。若生成文件节点,则代表装载驱动成功!

    (3)若需要卸载模块文件,可以通过以下命令:

    #rmmod class_reg_unreg.ko

    关于该驱动的测试程序,请参考“Android中字符设备驱动和应用实例(二) 应用部分

  • 相关阅读:
    ZJCTF预赛一个.py的逆向题
    if(a)是什么意思
    整理OD一些快捷键和零碎知识点
    NSCTF-Reverse02 超级详细且简单的办法搞定
    CTF实验吧——证明自己吧
    Beat our dice game and get the flag 击败我们的骰子游戏拿到旗子
    CTF-Keylead(ASIS CTF 2015)
    【第三届强网杯】两道杂项题的wp
    【实验吧】该题不简单——writeup
    嵩天老师python网课爬虫实例1的问题和解决方法
  • 原文地址:https://www.cnblogs.com/skywang12345/p/driver_char01.html
Copyright © 2011-2022 走看看