ARM&Linux基础
+ -

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

0 篇笔记 写笔记

Linux设备驱动基础
驱动安装&卸载驱动的安装一般使用insmod,modprobe,卸载会使用rmmodinsmod命令只会安装该驱动模块,如果该驱动模块存在别的模块依赖,而刚好系统没有安装依赖模块,该驱动模块会安装失败。modproebe命令会从/lib/modules/
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!