zoukankan      html  css  js  c++  java
  • 17. 在内核源码上增加自定义驱动

    TOC

    前言

    在了解了Kconfig和Makefile的相关原理后,是不是有种在源码上自定义驱动的冲动。

    放心,接下来,我会满足你的小小欲望。

    编写简单的自定义驱动

    hello_dev.c

    #include <linux/module.h>  
    #include <linux/kernel.h>  
    #include <linux/fs.h>  
    #include <linux/init.h>  
    #include <linux/delay.h>  
    #include <linux/irq.h>  
    #include <linux/poll.h>  
    #include <linux/cdev.h>  
    #include <linux/device.h>
    
    
    #define HELLO_CNT   1  
    
    
    //主设备号为0,表示动态分配设备号 
    dev_t dev = 0;
    static int major = 0;   
    static int minor = 0;
    
    static struct cdev *hello_cdev[HELLO_CNT];
    static struct class *hello_class = NULL;
    static struct class_device * hello_class_dev[HELLO_CNT];
    
    
    
    
    //文件操作结构体
    static const struct file_operations fops = 
    {
        .owner = THIS_MODULE,
        //.open = hello_open,
        //.release = hello_release,
        //.read = hello_read,
        //.write = hello_write,
    };
    
    
    static void setup_cdev(int index)
    {
        int err, devno = MKDEV(major, index);
    
        cdev_init(hello_cdev[index], &fops);
        hello_cdev[index]->owner = THIS_MODULE;
        hello_cdev[index]->ops = &fops;
        err = cdev_add(hello_cdev[index], devno, 1);
        if(err)
        {
            printk(KERN_NOTICE "Error %d adding hello%d", err, index);
        }
    }
    
    static void __init hello_init(void)
    {
    
    
        //申请设备号,动态or静态
        int ret = 0;
        if(major)
        {
            //为字符设备静态申请第一个设备号
            dev = MKDEV(major, minor);
            ret = register_chrdev_region(dev, HELLO_CNT, "hello");
        }
        else
        {
            //为字符设备动态申请一个设备号
            ret = alloc_chrdev_region(&dev, minor, HELLO_CNT, "hello");
            major = MAJOR(dev);
        }
    
    
        //构造cdev设备对象
        int i = 0;
        for(i = 0; i < HELLO_CNT; ++i)
        {
            hello_cdev[i] = cdev_alloc();
    
    
        }
    
    
        //初始化设备对象    
        for(minor = 0; minor < HELLO_CNT; ++minor)
        {
            setup_cdev(minor);
        }
    
        hello_class = class_create(THIS_MODULE, "hello");
        for(minor = 0; minor < HELLO_CNT; ++minor)
        {
            hello_class_dev[minor] = device_create(hello_class, NULL, MKDEV(major, minor), NULL, "hello%d",minor);
        }
    
    
    }
    
    
    
    
    static void __exit hello_exit(void)
    {
        for(minor = 0; minor < HELLO_CNT; ++minor)
        {
            device_destroy(hello_class, MKDEV(major, minor));
        }
        class_destroy(hello_class);
    
    
        //从内核注销cdev设备对象
        cdev_del(hello_cdev);
    
        //回收设备号
        unregister_chrdev_region(dev, HELLO_CNT);
    }
    
    
    module_init(hello_init);  
    module_exit(hello_exit);  
    
    
    MODULE_LICENSE("GPL");  

    创建相关目录和文件

    linux内核的驱动都是放在drivers目录进行管理的。

    1.于是,先在drivers目录下,创建test目录;然后将写好的驱动程序hello_dev.c放置这个目录下。

    2.在drivers/test目录下新建一个文件Kconfig, 并在填写如下内容:

    config HELLO
        tristate "This is hello driver"
        help
        just for test!!

    3.在drivers/test目录下新建一个文件Makefile, 并在填写如下内容:

    obj-$(CONFIG_HELLO) += hello_dev.o

    关联上一级目录的Kconfig和Makefile

    1. drivers/Kconfig文件上加入一行内容source drivers/test/Kconfig
    2. drivers/Makefile文件上加入一行内obj-y += test/

    配置&编译

    使用菜单配置:$ make menuconfig

    编译内核:$ make -j4

    编译模块:$ make modules

    查看编译结果:

    $ find . -name "hello_dev.ko"
    ./drivers/test/hello_dev.ko
  • 相关阅读:
    Cocos2d-x游戏移植到Android平台
    Alice and Bob
    Hamming Codes
    Fire逃生
    Java中面向对象的理解
    常见的几个算法
    数组的介绍
    Java 中的数据类型
    Java 初相识
    JavaScript 数据类型 (续)
  • 原文地址:https://www.cnblogs.com/standardzero/p/12551189.html
Copyright © 2011-2022 走看看