第 2 篇 小白前置知识急救包!RK 安卓驱动开发必备知识点,一篇补全

目录

[一、驱动开发必备 C 语言核心:只讲必用的,不搞无用内卷](#一、驱动开发必备 C 语言核心:只讲必用的,不搞无用内卷)

[1. 指针:驱动的灵魂,绕不开的核心](#1. 指针:驱动的灵魂,绕不开的核心)

[驱动里必用的指针用法,你只需要掌握这 4 个:](#驱动里必用的指针用法,你只需要掌握这 4 个:)

[2. 结构体:驱动里的 "数据容器"](#2. 结构体:驱动里的 “数据容器”)

[3. Linux 文件 IO:驱动的核心操作接口](#3. Linux 文件 IO:驱动的核心操作接口)

[4. 内核内存管理:驱动里的内存分配](#4. 内核内存管理:驱动里的内存分配)

[二、Linux 核心基础:不用背,会用这些就够了](#二、Linux 核心基础:不用背,会用这些就够了)

[1. 驱动开发必备 Linux 命令,按用途分类给你整理好了](#1. 驱动开发必备 Linux 命令,按用途分类给你整理好了)

(1)文件操作命令(最常用,每天都要用)

(2)权限管理命令(驱动必用,不然设备访问不了)

(3)编译相关命令(编译驱动、内核必用)

[(4)日志查看与调试命令(驱动调试的核心,找 bug 全靠它)](#(4)日志查看与调试命令(驱动调试的核心,找 bug 全靠它))

(5)文本编辑命令(改代码、改配置必用)

[2. Linux 核心概念,必须懂的底层逻辑](#2. Linux 核心概念,必须懂的底层逻辑)

[(1)Linux 目录结构,重点记这几个和驱动相关的目录](#(1)Linux 目录结构,重点记这几个和驱动相关的目录)

(2)内核态与用户态,最核心的边界

三、安卓系统基础:重点搞懂和驱动相关的分层架构

安卓系统四层架构,重点关注和驱动相关的两层

再讲一遍:安卓驱动的完整数据流转路径

[四、瑞芯微 SDK 全貌:拿到 SDK 再也不懵了](#四、瑞芯微 SDK 全貌:拿到 SDK 再也不懵了)

[先讲:SDK 是什么?从哪里来?](#先讲:SDK 是什么?从哪里来?)

[RK SDK 核心目录结构,重点标红给你](#RK SDK 核心目录结构,重点标红给你)

[小白必记的 4 个核心目录,90% 的开发工作都在这里:](#小白必记的 4 个核心目录,90% 的开发工作都在这里:)

五、小白学习工具包:必备软件、资料渠道全汇总

[1. 必备软件清单,全是免费好用的](#1. 必备软件清单,全是免费好用的)

[2. 学习资料渠道,全是新手友好的](#2. 学习资料渠道,全是新手友好的)

结尾说两句


【本文首发于 CSDN,作者:黒漂技术佬,未经授权禁止转载】

大家好,我是黒漂技术佬。上一篇扫盲文发出去之后,后台又炸了,小白兄弟们统一反馈:

"佬,我看懂了要学啥,但是我 C 语言忘光了,Linux 命令也只会个 ls cd,有没有一篇能把所有前置知识补全的?不用我到处找资料的那种"

安排!这篇文章,就是专门给零基础小白准备的前置知识急救包 。我不会给你讲大学课本里那些没用的理论,只讲 RK 安卓驱动开发里必用、高频、绕不开的知识点,零基础也能看懂,学完这篇,后面的环境搭建、驱动实战,你就能完全跟上,不会再出现 "每个字都认识,连起来看不懂" 的情况。

废话不多说,直接上干货。


一、驱动开发必备 C 语言核心:只讲必用的,不搞无用内卷

C 语言是驱动开发的母语,安卓驱动的内核部分,100% 都是用 C 语言写的。很多小白说 "我 C 语言没学好,能不能学驱动?",别慌,你不用把 C 语言学到精通,只需要把下面这几个核心知识点吃透,就足够入门驱动开发了。

1. 指针:驱动的灵魂,绕不开的核心

指针是 C 语言的灵魂,也是驱动里用的最多的语法,没有之一。很多小白觉得指针难,其实用大白话讲,指针就两个核心:指针,就是一个存储内存地址的变量,它指向的是一块内存的位置,而不是内存里存的数据。

举个通俗的例子:你把一个快递(数据)放在了快递柜的 3 号柜(内存地址),指针就是一张写着 "3 号柜" 的纸条,它本身不是快递,但是你通过这张纸条,就能找到快递柜里的快递,还能修改里面的东西。

驱动里必用的指针用法,你只需要掌握这 4 个:
  1. 普通指针与取地址、解引用

    c

    运行

    复制代码
    int a = 10;     // 定义一个int变量a,存在内存里
    int *p = &a;    // 定义一个int类型的指针p,&a是取a的内存地址,p指向a的地址
    *p = 20;        // 解引用,通过指针p修改它指向的内存里的数据,也就是把a改成20

    小白避坑:int *p里的*是用来定义指针的,*p里的*是用来解引用的,别搞混。

  2. 结构体指针 驱动里到处都是结构体,比如内核里的file_operationscdev,全是结构体,而操作结构体,90% 都是用结构体指针。

    c

    运行

    复制代码
    // 定义一个驱动里常用的设备结构体
    struct led_dev {
        int gpio_num;       // LED对应的GPIO编号
        char dev_name[20];  // 设备名称
    };
    
    struct led_dev led;     // 定义一个结构体变量
    struct led_dev *p_led = &led; // 定义结构体指针,指向led的地址
    
    // 结构体指针用->访问成员,结构体变量用.访问成员
    p_led->gpio_num = 10;  // 等价于 led.gpio_num = 10;

    小白必记:结构体指针用->访问成员,结构体变量用.访问成员,驱动里 90% 的场景都是用结构体指针。

  3. 函数指针 驱动的核心,就是用函数指针把我们写的驱动函数,注册到内核里。比如字符设备驱动里的file_operations结构体,里面全是函数指针,你必须懂。

    c

    运行

    复制代码
    // 定义一个函数,对应驱动里的open操作
    int led_open(struct inode *inode, struct file *filp)
    {
        printk("LED设备被打开了\n");
        return 0;
    }
    
    // 定义file_operations结构体,用函数指针把led_open绑定到open成员
    static const struct file_operations led_fops = {
        .owner = THIS_MODULE,
        .open = led_open,  // 函数指针赋值,把我们写的led_open函数,绑定到open操作
    };

    大白话讲:函数指针,就是把一个函数的入口地址,赋值给结构体里的成员,当内核要执行 open 操作的时候,就会自动调用我们写的 led_open 函数。这就是字符设备驱动的核心机制,必须懂。

  4. 空指针与野指针避坑这是新手写驱动最容易导致内核崩溃的问题:

    • 空指针:指针指向NULL(0 地址),对空指针解引用,内核直接 panic 崩溃;
    • 野指针:指针指向的内存是随机的、未申请的,对野指针操作,会直接修改内核的随机内存,导致系统崩溃、数据错乱。小白红线:使用指针前,必须先给它赋值合法的内存地址,绝对不能对未初始化的指针进行操作。

2. 结构体:驱动里的 "数据容器"

结构体,就是把多个不同类型的变量,打包成一个整体,方便管理。驱动里,我们会把一个设备的所有信息(GPIO 编号、设备名称、设备号、私有数据等),都打包在一个结构体里,这是驱动开发的标准写法。

你只需要掌握结构体的定义、初始化、结构体指针的用法,就足够了,上面讲结构体指针的时候已经给了例子,这里就不重复了。

3. Linux 文件 IO:驱动的核心操作接口

Linux 里有一个核心思想:一切皆文件 。所有的硬件设备,在 Linux 里都会被抽象成一个文件,放在/dev目录下,比如 LED 设备,就是/dev/led

我们对硬件设备的所有操作(打开、读、写、控制),本质上都是对这个设备文件的操作。而驱动里的核心函数,就是和这些文件 IO 操作一一对应的:

表格

用户空间文件 IO 函数 驱动里对应的函数指针 作用
open() .open 打开设备文件,初始化设备
read() .read 从设备里读取数据(比如读取传感器数据)
write() .write 向设备里写数据(比如控制 LED 亮灭)
ioctl() .unlocked_ioctl 对设备进行自定义控制(比如设置 PWM 频率)
close() .release 关闭设备文件,释放资源

这就是字符设备驱动的核心框架,你把这个对应关系搞懂了,后面写驱动就会豁然开朗。

4. 内核内存管理:驱动里的内存分配

驱动运行在内核空间,和用户空间的内存管理完全不一样,你不能用用户空间的malloc()free(),必须用内核提供的内存分配函数,入门阶段你只需要掌握两个:

  1. kmalloc():分配连续的物理内存,用于小内存分配,驱动里最常用,对应释放函数kfree()
  2. vmalloc():分配非连续的虚拟内存,用于大内存分配,对应释放函数vfree()

小白避坑:内核空间的内存资源极其宝贵,分配的内存用完必须释放,绝对不能出现内存泄漏,不然会导致系统崩溃。


二、Linux 核心基础:不用背,会用这些就够了

很多小白一听到 Linux 就头大,觉得要背几百个命令,其实完全不用。驱动开发入门阶段,你只需要掌握下面这些必备的命令和核心概念,就足够了,不用背,用多了自然就记住了。

1. 驱动开发必备 Linux 命令,按用途分类给你整理好了

(1)文件操作命令(最常用,每天都要用)

表格

命令 作用 驱动开发里的高频场景
ls 查看目录下的文件 查看驱动目录、编译生成的文件
cd 切换目录 进入内核源码目录、驱动目录
mkdir 创建目录 创建自己的驱动目录
cp 复制文件 / 目录 复制驱动源码、镜像文件
mv 移动 / 重命名文件 重命名驱动文件、移动编译产物
rm 删除文件 / 目录 删除编译生成的临时文件,rm -rf慎用!
cat 查看文件内容 查看设备树文件、驱动源码、内核日志
touch 创建空文件 创建驱动的.c 文件、Makefile 文件
(2)权限管理命令(驱动必用,不然设备访问不了)

Linux 里所有的文件都有权限限制,设备文件也一样,如果你不给设备文件设置读写权限,安卓 App 根本访问不了,这两个命令必须会:

  • chmod:修改文件权限,最常用的是chmod 777 /dev/led,给 led 设备文件全开权限(入门测试用,量产要注意权限安全);
  • chown:修改文件所属用户 / 用户组,用于修改设备文件的所属者,让安卓系统能访问。
(3)编译相关命令(编译驱动、内核必用)
  • gcc:C 语言编译器,编译测试程序必用;
  • make:执行 Makefile 编译脚本,编译内核、驱动全靠它,最常用的是make -j8,用 8 线程编译,速度更快;
  • make clean:清除之前的编译产物,重新编译的时候必用。
(4)日志查看与调试命令(驱动调试的核心,找 bug 全靠它)
  • dmesg:查看内核打印日志,驱动里用printk()打印的调试信息,全用这个命令看,驱动调试必用!高频用法:dmesg | grep led,过滤只看和 led 相关的日志;
  • cat /proc/kmsg:实时查看内核日志,和 dmesg 配合使用;
  • lsmod:查看当前内核加载的驱动模块;
  • insmod:加载驱动模块,比如insmod led_drv.ko
  • rmmod:卸载驱动模块,比如rmmod led_drv
  • mknod:创建设备文件,手动创建设备节点的时候用。
(5)文本编辑命令(改代码、改配置必用)
  • vi/vim:Linux 里最常用的文本编辑器,入门阶段你只需要掌握这几个操作就够了:
    1. vim led_drv.c:打开 / 创建文件;
    2. i进入编辑模式,就能写代码了;
    3. ESC退出编辑模式,输入:wq保存并退出,输入:q!强制退出不保存。

别去学那些花里胡哨的 vim 操作,入门阶段能改代码、保存退出就够了,等你熟练了再慢慢学进阶操作。

2. Linux 核心概念,必须懂的底层逻辑

(1)Linux 目录结构,重点记这几个和驱动相关的目录

Linux 的目录结构是树形的,根目录是/,所有的文件都在根目录下面,入门阶段你只需要记住这几个核心目录:

  • /dev:设备文件目录,所有的硬件设备文件都在这里,我们写的驱动设备,也会在这里生成对应的文件,比如/dev/led
  • /proc:虚拟文件系统,用于查看内核状态、进程信息、驱动信息,比如/proc/devices可以查看当前系统注册的设备号;
  • /sys:虚拟文件系统,和设备树、驱动模型强相关,驱动调试的时候经常用;
  • /home:用户目录,我们的开发环境、SDK、源码,一般都放在这里;
  • /lib:库文件目录,存放内核模块、共享库文件。
(2)内核态与用户态,最核心的边界

这是 Linux 最核心的概念,也是小白必须懂的:Linux 系统把内存分成了两个空间:内核态用户态

  • 用户态:应用程序运行的空间,权限很低,不能直接操作硬件、不能直接访问内核内存,所有的操作都要通过内核提供的系统调用完成;
  • 内核态:Linux 内核、驱动运行的空间,拥有最高权限,可以直接操作硬件、访问所有内存、管理整个系统的资源。

我们写的驱动,就是运行在内核态的,而安卓 App 是运行在用户态的,两者不能直接互相访问内存,必须通过内核提供的copy_from_user()copy_to_user()函数,完成用户空间和内核空间的数据交互,这是驱动开发里的核心操作,后面实战会详细讲。

小白红线:内核态里绝对不能做的事 ------ 不能用用户态的malloc()printf()等函数,不能在中断上下文里睡眠,不能访问用户空间的内存,不然内核直接崩溃。


三、安卓系统基础:重点搞懂和驱动相关的分层架构

上一篇扫盲文里,我已经给大家讲了安卓的分层架构,这里再给大家深入讲一下和驱动开发强相关的部分,让你彻底搞懂,我们写的驱动,是怎么和安卓系统联动的。

安卓系统四层架构,重点关注和驱动相关的两层

安卓系统从上到下,分为四层,我们做驱动开发,重点关注下面两层,上面两层只需要懂基本的交互逻辑就行:

  1. 应用层(App 层):用户能看到的所有安卓 App,都在这一层,比如我们写的控制 LED 的 App,运行在用户态,权限最低,不能直接操作驱动;
  2. 框架层(Framework 层) :安卓系统提供的 Java API 集合,比如CameraManagerInputManager,App 通过调用这些 API,实现和系统的交互。Framework 层运行在用户态,通过 JNI 接口,调用底层的 HAL 层代码;
  3. 硬件抽象层(HAL 层):重点中的重点!这是连接 Framework 层和内核驱动的桥梁,用 C/C++ 编写,运行在用户态。它定义了一套标准的接口,Framework 层只需要调用这套标准接口,不用关心底层驱动是怎么实现的;而硬件厂商只需要按照这套接口,实现自己的硬件逻辑,就能适配安卓系统。
  4. Linux 内核层:我们写的驱动就在这一层,运行在内核态,拥有最高权限,直接操作硬件,向上给 HAL 层提供设备文件操作接口。

再讲一遍:安卓驱动的完整数据流转路径

以 "App 点击按钮,控制 LED 亮灭" 为例,给你讲清楚每一步的流转,彻底打通你的任督二脉:

  1. 安卓 App 里,用户点击 "开灯" 按钮,App 调用 Framework 层提供的自定义 API;
  2. Framework 层的 Java API,通过 JNI 接口,调用 HAL 层里的 C/C++ 函数;
  3. HAL 层的函数,通过文件 IO 接口(open/write),打开/dev/led设备文件,向内核驱动发送 "开灯" 的指令;
  4. 内核驱动接收到 HAL 层的指令,操作对应的 GPIO 口,输出高电平,点亮 LED 灯;
  5. 关灯的流程,完全反过来,一模一样。

你看,整个流程里,内核驱动只是其中的一环,HAL 层是连接上层和底层的核心桥梁,这就是为什么我一直强调,安卓驱动开发必须打通全链路,只写内核驱动,App 根本用不了。


四、瑞芯微 SDK 全貌:拿到 SDK 再也不懵了

很多小白拿到瑞芯微的 SDK,一看几百个目录,直接懵了,根本不知道哪个目录是干嘛的,该去哪里写驱动。今天我给你把 RK SDK 的目录结构扒得明明白白,告诉你哪些是重点目录,哪些入门阶段根本不用碰。

先讲:SDK 是什么?从哪里来?

SDK(Software Development Kit,软件开发工具包),就是瑞芯微官方给我们提供的,包含了完整的安卓源码、Linux 内核源码、U-Boot 源码、驱动源码、编译工具、板级配置文件的完整开发包。我们做 RK 平台的安卓驱动开发,所有的工作,都是在这个 SDK 里完成的。

SDK 获取渠道

  1. 首选:你买的开发板的厂商,会给你提供适配好对应开发板的 SDK,不用自己从零适配,新手直接用这个,省 90% 的事;
  2. 官方渠道:瑞芯微开发者社区,需要企业资质申请,个人新手很难拿到,不用纠结。

RK SDK 核心目录结构,重点标红给你

我以 RK3568 的安卓 11 SDK 为例,给你讲核心目录,入门阶段,你只需要关注我标红的 4 个目录就行,其他的不用碰,别瞎改,改坏了编译不过:

plaintext

复制代码
RK3568_Android11_SDK/
├── u-boot/       # U-Boot源码,系统启动的第一阶段,入门阶段不用改,知道是干嘛的就行
├── kernel/       # 【重点中的重点】Linux内核源码,我们的驱动代码、设备树,全在这里面
│   ├── drivers/  # 内核驱动目录,我们写的驱动代码,就放在这个目录对应的子目录里
│   └── arch/arm64/boot/dts/rockchip/  # 【重点】RK平台设备树目录,板级设备树全在这里
├── hardware/     # 【重点】安卓HAL层源码,我们写的HAL层代码,就在这里面
│   └── rockchip/ # RK官方提供的HAL层适配代码,我们自己的HAL层代码也放在这里
├── device/       # 【重点】板级配置文件,开发板对应的分区配置、编译配置、硬件适配配置
├── out/          # 编译输出目录,编译好的镜像文件、固件,全在这里面
├── build/        # 安卓编译脚本,入门阶段不用改
├── external/     # 安卓第三方开源库,入门阶段不用改
├── frameworks/   # 安卓Framework层源码,进阶阶段再碰,入门不用改
└── system/       # 安卓系统核心库,入门阶段不用改
小白必记的 4 个核心目录,90% 的开发工作都在这里:
  1. kernel 目录 :内核源码目录,我们写的 Linux 内核驱动,全放在kernel/drivers/对应的子目录里,比如 GPIO 驱动放在drivers/gpio/,LED 驱动放在drivers/leds/,字符设备驱动可以自己建个drivers/char/xxx目录。设备树文件全在kernel/arch/arm64/boot/dts/rockchip/目录里,我们修改设备树,就是改这个目录里的 dts/dtsi 文件。
  2. hardware 目录:HAL 层源码目录,我们写的安卓 HAL 层代码,全在这里面,实现和内核驱动的交互,给 Framework 层提供接口。
  3. device 目录:板级配置目录,开发板对应的编译配置、分区配置、屏幕适配配置,都在这里面,入门阶段只需要看懂,不用大改。
  4. out 目录:编译输出目录,我们编译好的内核镜像、boot.img、system.img、完整的烧录固件,全在这里面,烧录的时候就是从这个目录里拿镜像。

五、小白学习工具包:必备软件、资料渠道全汇总

最后,给大家整理了入门阶段必备的工具和资料渠道,不用你到处找,直接照着用就行。

1. 必备软件清单,全是免费好用的

表格

软件名称 作用 下载渠道
VMware Workstation Player 虚拟机软件,用来装 Ubuntu 开发环境,免费版足够用 VMware 官网
Ubuntu 20.04 LTS 开发环境系统,强烈推荐用 20.04 版本,别用 22.04 以上的,兼容性差,很多 SDK 编译不过 Ubuntu 官网
MobaXterm 串口调试、SSH 连接神器,集成了串口、SSH、FTP 等功能,比 SecureCRT 好用,免费版足够 MobaXterm 官网
RKDevTool 瑞芯微官方烧录工具,用来给开发板烧录固件,免费 瑞芯微开发者社区、开发板厂商资料
DriverAssitant 瑞芯微 USB 驱动,烧录的时候必须装,不然电脑识别不到开发板 同上
VS Code 代码编辑器,看内核源码、写驱动代码神器,比 Source Insight 轻量,免费 VS Code 官网
Notepad++ 文本编辑器,看配置文件、改设备树超好用,免费 Notepad++ 官网

2. 学习资料渠道,全是新手友好的

  1. 开发板厂商配套资料:野火、正点原子、韦东山的 RK3568 开发板,都有配套的用户手册、教程、源码,新手入门首选,比网上零散的教程靠谱得多;
  2. 瑞芯微开发者社区:官方文档、SDK、芯片手册的唯一官方渠道,进阶必看;
  3. CSDN:国内最大的嵌入式技术社区,遇到问题直接搜,90% 的坑都有人踩过,有解决方案;
  4. Linux 内核官方文档:内核驱动开发的权威文档,进阶必看;
  5. 安卓官方开发者文档:安卓 HAL 层、Framework 层的权威文档,进阶必看。

结尾说两句

这篇文章,把 RK 安卓驱动开发必备的所有前置知识,全给你补全了。不用你再到处找资料,把这篇文章里的知识点吃透,你就已经超过了 80% 刚入门的小白,后面的环境搭建、驱动实战,你就能完全跟上。

下一篇,我们正式进入实操环节,保姆级手把手带你搭建 RK 安卓驱动开发环境,从 Ubuntu 虚拟机安装、依赖库配置,到 SDK 编译、镜像烧录,一步不落,所有报错都给你解决方案,保证你一次搭建成功,不踩坑。

我是黒漂技术佬,关注我,带你零基础入门 RK 安卓驱动开发,不迷路。有任何知识点不懂的,评论区留言,我都会一一回复。

相关推荐
Zevalin爱灰灰2 小时前
零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(一)
单片机·物联网·嵌入式·esp8266
zh路西法2 小时前
【C语言简明教程提纲】(四):结构体与文件定义和操作
android·c语言·redis
wsoz3 小时前
GCC编译
linux·c语言·嵌入式·gcc
七七肆十九4 小时前
PTA 习题9-1 时间换算
c语言·算法
济6174 小时前
STM32F103 时钟系统从原理到实战:8MHz 到 72MHz 配置与 LED 闪烁实验---STM32 HAL库专栏
stm32·嵌入式·stm32hal库编程
charlie1145141914 小时前
2026年IMX6ULL正点原子Alpha开发板学习方案——U-Boot完全移植概览:从官方源码到你的自制板,这条路有多远
linux·学习·嵌入式·uboot·嵌入式linux·工程实践·编程指南
条tiao条4 小时前
从 “Top-K 问题” 入门二叉堆:C 语言从零实现与经典应用
c语言·算法·深度优先
Zevalin爱灰灰4 小时前
零基础入门学用物联网(ESP8266) 第一部分 基础知识篇(二)
单片机·物联网·嵌入式·esp8266
1231566805 小时前
PAT 1017 A除以B
c语言·数据结构·算法·pat考试