17. 在内核源码上增加自定义驱动
前言
在了解了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
- 在
drivers/Kconfig
文件上加入一行内容source drivers/test/Kconfig
- 在
drivers/Makefile
文件上加入一行内obj-y += test/
配置&编译
使用菜单配置:$ make menuconfig
编译内核:$ make -j4
编译模块:$ make modules
查看编译结果:
$ find . -name "hello_dev.ko"
./drivers/test/hello_dev.ko