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
posted @ 2020-03-23 11:40  standardzero  阅读(373)  评论(0编辑  收藏  举报