# linux_drive **Repository Path**: li-tuo/linux_drive ## Basic Information - **Project Name**: linux_drive - **Description**: 常用linux驱动模块 - **Primary Language**: C - **License**: GPL-3.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2020-09-16 - **Last Updated**: 2021-02-18 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # linux_drive #### 介绍 linux常见驱动模块 #### 基本概念 1. Linux中一切皆文件,驱动加载成功后会在 /dev 目录下生成相应的文件,应用程序通过对这个名为 /dev/xxx 的文件进行相应的操作即可实现对硬件的操作 2. 应用程序运行在用户空间,linux驱动属于内核部分,运行于内核空间;在用户空间想要实现对内核的操作,eg:使用open函数打开 /dev/led 驱动,由于用户空间不能直接对内核进行操作,必须使用 “系统调用” 方法实现从用户空间 “陷入” 到内核空间,以此实现对底层驱动的操作 应用程序open()函数 ---> C库中的open()函数 ---> open()系统调用 ---> q驱动的open()函数 应用程序 C库 内核 具体驱动 #### 主要代码功能 1. 编写设备驱动模块开发 2. 编写测试APP来测试驱动 #### 字符设备驱动的开发流程 ##### 驱动模块的加载和卸载 1. linux驱动有两种运行方式,1、将驱动编译进linux内核,当linux内核启动的时候会自动运行驱动程序;2、将驱动编译成模块(xxx.ko),在linux内核启动后使用 “insmod” 命令加载驱动模块;在调试阶段选择将其编译为模块,方便。当驱动开发完成,将驱动编译进linux内核, 2. 注册模块加载函数:module_init(xxx_init); xxx_init(驱动入口函数)--->需要注册的具体函数,insmod命令加载驱动时会调用此函数 3. 注册模块卸载含数:module_exit(xxx_exit); xxx_exit(驱动出口函数)--->需要注册的具体函数,rmmod命令卸载驱动时会调用此函数 4. 加载驱动模块命令:insmod---> 不能解决模块的依赖关系; modprobe---> 会分析模块的依赖关系,将所有依赖模块都加载到内核中; 5. 推荐使用 modprobe 命令来加载驱动,modprobe 命令默认会去/lib/modules/目录中查找模块,自己制作的根文件系统中是不会有这个目录的,需要手动创建 6. 卸载驱动模块命令:rmmod; modprobe -r,可以卸载掉驱动的其他依赖模块,注意:前提是依赖模块此时没有被其他模块使用; 推荐使用rmmod命令 7. 编写驱动 ##### 字符设备注册和注销 1. 驱动模块加载成功以后需要注册字符设备,卸载驱动模块的时候需要注销掉字符设备 2. 通常:字符设备的注册在驱动模块的入口函数 xxx_init 中进行,字符设备的注销在驱动模块的出口函数 xxx_exit 中进行 ##### 实现设备的具体操作函数 1. file_operations 结构体是设备的具体操作函数,在初始化时,需要分析一下需求,也就是要对进行操作的设备确定需要进行那些操作,这样才能知道应该实现那些操作函数 ##### 添加LICENSE和作者信息 1. MODULE_LICENSE("GPL") //添加模块LICENSE信息 --->必要的,否则编译报错 2. MODULE_AUTHOR("lituo") //添加模块作 #### Linux设备号 ##### 设备号的组成 1. 设备号出现的目的,方便linux管理众多的device设备 2. 设备号由主设备号和次设备号两部分组成,主设备号表示某一个具体的驱动,次设备号表示使用这个驱动的各个设备 3. linux用dev_t的数据类型表示设备号,eg: typedef __u32 __kernel_dev_t; typedef __kernel_dev_t dev_t; typedef unsigned int __u32; 4. 由上知,dev_t 是unsigned int 类型,一个32的数据类型,高12位为主设备号,低20位为次设备号 ##### 设备号的分配 1. 静态分配设备号,使用 `cat/proc/devices` 命令可以查看当前系统中所有已经使用的设备号,开发者可以静态的指定一个人设备号(别使用已使用的设备) 2. 动态分配设备号,linux社区推荐使用动态分配设备号,在注册字符设备之前先申请一个设备号,系统会自动给你一个没有被使用的设备号,这样就避免了冲突, 卸载驱动的时候释放掉这个设备号即可。设备号申请函数如下: ` int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) ` # 测试 1. 加载驱动 modprobe chrdevbase.ko 2. 进入/dev 查看设备文件,/dev/chrdevbase,实际没有,因为我们没有创建设备节点。 mknod /dev/chrdevbase c 200 0 3. 测试 ./chrdevbaseAPP /dev/chrdevbase # chrdevbase 虚拟设备驱动的完善