用笔记的方式来记录学习Linux驱动的过程
Linux驱动自学记录
先简单描述一下使用的平台和辅助资料吧:
《LINUX设备驱动程序(第三版)》
《Linux设备驱动开发详解 基于最新的Linux 4.0内核》
《嵌入式Linux设备驱动程序开发指南》(原书第2版)
开发板采用的是韦东山老师的imx6ull Pro
开发环境Ubuntu 18.02
笔记的写作思路是一边做实验,一边总结。
Linux驱动设计对于大部分工程师而言,就是利用Linux kernel提供的API接口进行设计,所以重要的工作是熟练掌握接口函数以及其中输入输出的应用场景。
包括但不限于:输入参数,返回值。。。。
驱动最简单的框架
驱动程序的必要几个元素:设备编号
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/kernel.h>
static int scull_major = 0;
static int scull_minor = 0;
static int scull_nr_devs = 0;
static dev_t my_cdev;
/**/
static int __init scull_drv_init(void)
{
int result;
printk("Scull DRV");
if(scull_major){
my_cdev = MKDEV(scull_major, scull_minor);
result = register_chrdev_region(my_cdev, scull_nr_devs, "Fix_scull");
}
else{
alloc_chrdev_region(&my_cdev, scull_major, scull_nr_devs, "Dynamic_scull");
}
return 0;
}
static void __exit scull_drv_exit(void)
{
printk("%s %s line %d\n",__FILE__, __FUNCTION__, __LINE__);
unregister_chrdev_region(my_cdev, 1);
}
module_init(scull_drv_init);
module_exit(scull_drv_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Rock <28406967@qq.com>");
MODULE_DESCRIPTION("This is a print init file");
分配和释放设备编号
下面是Linux Kernel的源代码
/**
* register_chrdev_region() - register a range of device numbers
* @from: the first in the desired range of device numbers; must include
* the major number.
* @count: the number of consecutive device numbers required
* @name: the name of the device or driver.
*
* Return value is zero on success, a negative error code on failure.
*/
int register_chrdev_region(dev_t from, unsigned count, const char *name)
{
struct char_device_struct *cd;
dev_t to = from + count;
dev_t n, next;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
if (next > to)
next = to;
cd = __register_chrdev_region(MAJOR(n), MINOR(n),
next - n, name);
if (IS_ERR(cd))
goto fail;
}
return 0;
fail:
to = n;
for (n = from; n < to; n = next) {
next = MKDEV(MAJOR(n)+1, 0);
kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
}
return PTR_ERR(cd);
}
/**
* alloc_chrdev_region() - register a range of char device numbers
* @dev: output parameter for first assigned number
* @baseminor: first of the requested range of minor numbers
* @count: the number of minor numbers required
* @name: the name of the associated device or driver
*
* Allocates a range of char device numbers. The major number will be
* chosen dynamically, and returned (along with the first minor number)
* in @dev. Returns zero or a negative error code.
*/
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
const char *name)
{
struct char_device_struct *cd;
cd = __register_chrdev_region(0, baseminor, count, name);
if (IS_ERR(cd))
return PTR_ERR(cd);
*dev = MKDEV(cd->major, cd->baseminor);
return 0;
}
insmod scull_drv.ko
cat /proc/devices
笔记:
- 现在最新都采用自动分配函数 alloc_chrdev_region
- dev_t 本质上是个int
- register_chrdev_region 中第一个参数如果输入0就是自动分配
- 用cat /proc/devices 查看生成的驱动
- 用dmesg | tail -10 查看打印的内容。