驱动工程搭建与字符设备驱动框架

一、驱动的编写

静态加载 , 驱动在zImage 中

1.编写驱动 .c

2.编译代码

.config Kconfig Makefile

3.通过 make menuconfig 勾选 需要编译的内容 <*>

4.zImage 中,会包含咱们的驱动的代码。 zImage 会变大。

5.需要开发板重新启动,新增的代码才能生效。

动态加载 ,生成ko文件,独立与zImage

1.编写驱动 .c

2.编译代码

修改Makefile obj-m += led.o

make modules产生ko文件

3.使用insmod 命令 , 手动加载(Linux 已经成功运行后)。 根据实际需要加载。不是zImage的一部分 。

rmode ,卸载模块。更加灵活。

字符设备重要的宏:

|--------------------------|-------------------------------------|
| 函数名 | 功能 |
| module_init | 驱动模块加载入口 |
| module_exit | 驱动模块卸载入口 |
| MODULE_LICENSE(_license) | MODULE_LICENSE("GPL") , |
| printk(char*s, ....); | 内核中,类似printf函数,不要输出 浮点数。这个等级需要配置文 件 |
| pr_info(fmt, ...) | 带输出等级的输出,一般信息 |
| pr_err(fmt, ...); | 带输出等级的输出 错误信息 |

在源码目录下编写自己的驱动

源码最顶层有个.config ,会决定那些文件被编译。 在源码目录中,每层都有Kconfig, Markfile . 最顶层层Make ,会调用子目录中的Makefile

drivers/char 下新建 mydevtest.c

cpp 复制代码
#include "linux/printk.h"
#include <linux/init.h>
#include <linux/module.h>
static int __init mymodule_init(void)
{
pr_info("i'm coming....,mymodule_init ok\n");
return 0;
} s
tatic void __exit mymodele_exit(void)
{
pr_info("mymodule_init byebye\n");
return;
} m
odule_init(mymodule_init);
module_exit(mymodele_exit);

如果需要编译这个文件。需要按以下步骤

1.在drivers/char 目录下创建.c文件

2.修改Kconfig

在Kconfig 中加入

cpp 复制代码
config MYMODULE #MYMODULE 这个是驱动控制变量名 在Makefile中要用
    tristate "mymodule inner kernel test" # 三态, Y,M N , bool 是 Y N
                                          # depends on ,依赖
    default y                             #选择的默认状态
    help                                  #说明信息
        driver test kconfig makefile

3.修改Makefile

4.make menuconfig ,进行勾选

5.make modules ->生成ko 文件。 复制到nfs/rootfs 下

6.模块的加载

cpp 复制代码
insmod myhell.ko
ls /sys/module
lsmod #查看加载了那些模块
rmmod #卸载模块

源码目录外编写驱动 (推荐)

工程的构建,在linux源码之外的地方编写代码。

目录的结构

cpp 复制代码
├── app
│ ├── app.c
│ └── Makefile
├── drv
│ ├── .clangd #clangd匹配脚本
│ ├── compile_commands.json -> /home/linux/imx6ull/linux-imxrel_imx_4.1.15_2.1.0_ga_alientek/compile_commands.json # 自动补齐文件
│ ├── drv.c
│ └── Makefile
└──
Makefile

drv的Makefile

MODULE_NAME:= drv 注意drv后面不能有空格,已经翻车多次。

先决条件, linux源码需要已经编译过了,才行。

make -C 进入目录

M= ,设置模块的路径, 咱们的模块路径和源码路径是不同的。

cpp 复制代码
MODULE_NAME:= drv
KER_DIR := /home/linux/imx6ull/linux-imx-rel_imx_4.1.15_2.1.0_ga_alientek
CUR_DIR := $(shell pwd)
obj-m += $(MODULE_NAME).o
all:
    make -C $(KER_DIR) M=$(CUR_DIR) modules
    cp $(MODULE_NAME).ko ~/nfs/rootfs
clean:
    make -C $(KER_DIR) M=$(CUR_DIR) clean
distclean:
    rm $(MODULE_NAME).ko
    make -C $(KER_DIR) M=$(CUR_DIR) distclean

app的Makefile

cpp 复制代码
SRC:=app.c
OBJ:=app
CC:=arm-linux-gnueabihf-gcc
all:
    $(CC) $(SRC) -o $(OBJ)
clean:
    rm $(OBJ)

顶层makefile

cpp 复制代码
all:
    make -C ./app all
    make -C ./drv all
clean:
    make -C ./app clean
    make -C ./drv clean

二、字符设备驱动框架

linux 系统中驱动的分类:

  • 字符设备驱动 gpio,i2c,spi,ad,uart,lcd,camera , 按照字节操作,有顺序要求。数据吞吐量小。比重大,占到95% 以上。
  • 块设备驱动 存储设备的驱动程序, emmc, sd, flash 类型设备。 随机数据访问,按照固定大小字节读写,数据吞吐量大。
  • 网络设备驱动 ,支持网络协议栈设备 。 wifi, blue, zigbee, can。

字符设备驱动编写的步骤

1 申请设备号,主次设备号 MKDEV, alloc_chrdev_region

2 注册设备号 register_chrdev_region , alloc_chrdev_region

3 初始化字符设备结构体 cdev_init(自动关联fops), cdev_add(驱动注册到内核),cdev_alloc (手动关联)

4 准备 file_operation , 注册 应用层对应的open,close,read, write函数。给函数指针赋值。

相关函数

1.cdev操作函数接口:

|------------|------------|
| 函数名 | 功能 |
| cdev_init | 初始化字符设备结构体 |
| cdev_alloc | 申请字符设备结构体 |
| cdev_add | 添加字符设备 |
| cdev_del | 删除字符设备 |

2.字符设备操作接口:

|--------------------------|---------------------------------------------------|
| 函数名 | 功能 |
| register_chrdev_region | 静态注册已知设备号范围(需提前确定主设备号) |
| alloc_chrdev_region | 动态分配设备号,并注册(内核自动分配主设备号) |
| unregister_chrdev_region | 释放注册的设备号 |
| register_chrdev | 注册设备号并关联file_operations结构体(早期内核使用, 2.6版本 以后尽量不使用) |
| unregister_chrdev | 注册注册的设备号(早期内核使用, 2.6版本以后尽量不使用) |

当创建设备类型,cat /proc/devices

出现设备类后,没有 具体的设备 。需要手动创建节点

创建具体的设备,主设备号 248 ,次设备号0

mknod /dev/led0 c 248 0

3.file_operation 结构体

相关推荐
发量惊人的中年网工1 小时前
SD-WAN 组网方案怎么选?跨地域与多分支企业的选型指南(含成本对比)
服务器·网络·数据库
第25小时记录1 小时前
[2026] Linux安装教程
运维·python
斯晨的AI笔记1 小时前
在服务器上跑 npm ci 四十分钟没装完,我打包把 node_modules 扔了过去
服务器·node.js
曦樂~2 小时前
Symmetric Ciphers对称加密
运维·服务器
mister_guo2 小时前
Elasticsearch:原理、Docker 安装与常用命令
大数据·运维·elasticsearch
Escalating_xu3 小时前
【Linux 网络编程】网络基础概念(下):IP、端口、Socket 与网络字节序,写代码前先打好基础
linux·网络·tcp/ip
刚入门的大一新生3 小时前
Linux-Ext系列文件系统
linux·运维·服务器
bmxy小明同学3 小时前
2026-10-11-幻觉治理
服务器·前端·javascript
灯澜忆梦3 小时前
【docker】#4 | Docker 自定义镜像与 Dockerfile
运维·docker·容器