Linux设备驱动基础
2025-11-13
22
0
驱动安装&卸载
驱动的安装一般使用insmod,modprobe,卸载会使用rmmod
- insmod命令只会安装该驱动模块,如果该驱动模块存在别的模块依赖,而刚好系统没有安装依赖模块,该驱动模块会安装失败。
- modproebe命令会从
/lib/modules/<kernel-version>目录中查找该模块依赖的模块,如果系统没有安装,会自动安装依赖模块。
kernelr version使用如下命令获取
uname -r
驱动安装
insmod drv.ko
modproebe drv.ko
rmmod drv.ko //modprobe -r drv.ko
使用modproebe命令时,ko模块最好放到
/lib/modules/<kernel-version>目录下,并在运行之前先运行depmod
查看当前系统设备版本号分配
cat /proc/devices
手动创建设备节点
mknod /dev/chrdevbase c 200 0
内存映射
内存映射是将物理地址转换成虚拟线性地址,相当于windows的MmMapIoSpace
- ioremap /iounmap
- MmMapIoSpace/MmUnmapIoSpace
读写寄存器
- WRITE_REGISTER_ULONG
- writel/writew/writeb/readl/readb/readw
驱动
字符驱动
imx6ull开发板默认LED灯是定时闪烁的,需要关闭
echo none > /sys/class/leds/sys-led/trigger // 改变 LED 的触发模式
register_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME, &chrdevbase_fops);
unregister_chrdev(CHRDEVBASE_MAJOR, CHRDEVBASE_NAME);
register_chrdev 和 unregister_chrdev 这两个函数是老版本驱动使用的函数,现在新的字符设备驱动已经不再使用这两个函数,而是使用Linux内核推荐的新字符设备驱动API函数。
设备号
老式的字符驱动使用register_chrdev时,需要手动指定设备号(是主设备号,这样子设备号就没有用上)。新的驱动时,可以向系统申请主设备号和子设备号。
/* newchrled设备结构体 */
struct newchrled_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
};
#define NEWCHRLED_CNT 1 /* 设备号个数 */
#define NEWCHRLED_NAME "newchrled" /* 名字 */
static int __init led_init(void)
{
//unregister_chrdev_region
if (newchrled.major) { /* 定义了设备号 */
newchrled.devid = MKDEV(newchrled.major, 0);
register_chrdev_region(newchrled.devid, NEWCHRLED_CNT, "newchrled");
} else { /* 没有定义设备号 */
alloc_chrdev_region(&newchrled.devid, 0, NEWCHRLED_CNT, "newchrled"); /* 申请设备号 */
newchrled.major = MAJOR(newchrled.devid); /* 获取分配号的主设备号 */
newchrled.minor = MINOR(newchrled.devid); /* 获取分配号的次设备号 */
}
printk("newcheled major=%d,minor=%d\r\n",newchrled.major, newchrled.minor);
/* 2、初始化cdev */
newchrled.cdev.owner = THIS_MODULE;
cdev_init(&newchrled.cdev, &newchrled_fops);
/* 3、添加一个cdev *///cdev_del
cdev_add(&newchrled.cdev, newchrled.devid, NEWCHRLED_CNT);
/* 4、创建类 */
newchrled.class = class_create(THIS_MODULE, "class_newchrled");//class_destroy
if (IS_ERR(newchrled.class)) {
return PTR_ERR(newchrled.class);
}
/* 5、创建设备 *///device_destroy
newchrled.device = device_create(newchrled.class, NULL, newchrled.devid, NULL, "newchrled");
if (IS_ERR(newchrled.device)) {
return PTR_ERR(newchrled.device);
}
retrun 0;
}
static void __exit led_exit(void)
{
/* 注销字符设备驱动 */
cdev_del(&newchrled.cdev);/* 删除cdev */
unregister_chrdev_region(newchrled.devid, NEWCHRLED_CNT); /* 注销设备号 */
//删除节点
device_destroy(newchrled.class, newchrled.devid);
//删除类
class_destroy(newchrled.class);
}
- /sys/class/创建的是类名对应的类目录
- /dev/创建的是设备名
root@ATK-IMX6U:~/rengedrivertest/newcharled# ls /sys/class | grep class
class_newchrled
root@ATK-IMX6U:~/rengedrivertest/newcharled# ls /dev/ | grep new
newchrled
整理
struct newchrled_dev{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct class *class; /* 类 */
struct device *device; /* 设备 */
int major; /* 主设备号 */
int minor; /* 次设备号 */
};
----
register_chrdev//unregister_chrdev
----
alloc_chrdev_region/register_chrdev_region //unregister_chrdev_region
cdev_init
cdev_add //cdev_del
class_create //class_destroy
device_create //device_destroy
ARM&Linux基础





