一、树莓派开发环境搭建
二、Linux文件系统的目录结构
三、树莓派Linux源码目录树分析
四、树莓派Linux源码配置
五、如何配置树莓派的Linux内核
六、树莓派Linux内核编译
七、配置启动参数的cmdline.txt
一、树莓派开发环境搭建
树莓派官网
raspberrypi
raspberrypi/tools
raspberrypi/linux/tree/rpi-4.14.y
先安装交叉编译工具链tools-master.zip
cp /mnt/hgfs/Share/tools-master.zip ./
unzip tools-master.zip 解压
cd /home/tan/raspberryPI/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
//gcc-linaro-arm-linux-gnueabihf-raspbian 32位
//gcc-linaro-arm-linux-gnueabihf-raspbian-x64 64位
arm-linux-gnueabihf-gcc ->arm-linux-gnueabihf-gcc-4.8.3
配置环境变量
echo $PATH // 获得当前环境变量的值
pwd // 获得当前路径
export PATH=$PATH:pwd
1. 临时有效,配置环境变量
PATH 环境变量
export PATH=/home/orangepi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/tan/raspberryPI/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
export PATH=$PATH:/home/tan/raspberryPI/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
2. 永久有效,配置环境变量,要改配置文件
修改工作目录下的 .bashrc
隐藏文件,配置命令终端的
vi /home/tan/.bashrc
在文件最后一行加入:
export PATH=/home/orangepi/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:/home/tan/raspberryPI/tools-master/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian-x64/bin
source /home/tan/.bashrc 加载配置文件,马上生效配置。
交叉编译工具链安装完毕
arm-liunx-gnueabihf-gcc -v
再安装linux-rpi-4.14.y.zip
unzip linux-rpi-4.14.y.zip
二、Linux文件系统的目录结构
Linux 文件系统的目录结构是由 Filesystem Hierarchy Standard(FHS,文件系统层次结构标准)定义的,这个标准规定了不同目录的用途和存储的内容。以下是 Linux 文件系统中一些常见的目录及其用途:
-
/bin:
- 存放系统中最基本的命令,如ls、cp、mv等,这些命令是用于系统修复的。
-
/boot:
- 包含了 Linux 内核和系统引导时所需的文件。通常包括 boot loader 的配置文件和内核镜像。
-
/dev:
- 包含设备文件,Linux 将设备表示为文件,通过这些文件访问硬件设备。
-
/etc:
- 存放系统的配置文件。几乎所有的系统配置文件都在这个目录下,包括网络配置、用户账户配置、软件包配置等。
-
/home:
- 存放用户的主目录,每个用户都有一个独立的子目录,例如 /home/username。
-
/lib 和 /lib64:
- 存放系统运行时所需的共享库文件,其中 /lib64 是用于存放 64 位系统的库文件。
-
/media:
- 用于挂载可移动媒体设备,例如 USB 驱动器、CD-ROM 等。
-
/mnt:
- 临时挂载点,通常用于手动挂载文件系统。
-
/opt:
- 存放可选的软件包,通常由第三方提供。
-
/proc:
- 虚拟文件系统,提供有关系统内核和进程的信息,例如 /proc/cpuinfo 提供了有关 CPU 的信息。
-
/root:
- 超级用户(root)的主目录。
-
/run:
- 存放系统运行时需要的临时文件,如 PID 文件和 sockets。
-
/sbin:
- 存放系统管理员使用的基本系统命令,例如 ifconfig、fdisk。
-
/srv:
- 存放服务相关的数据。
-
/sys:
- 虚拟文件系统,提供有关内核和设备的信息。
-
/tmp:
- 用于存放临时文件。
-
/usr:
- 包含用户二进制文件和库文件,通常不包含用户主目录。
-
/var:
- 包含经常变化的文件,如日志文件、数据库文件等。
-
/etc/opt:
- 用于存放 /opt 中软件包的配置文件。
-
/usr/local:
- 用户自行安装的软件包的默认安装位置。
这只是 Linux 文件系统的一小部分,不同的 Linux 发行版可能会有一些变化,但大多数发行版都遵循 FHS 标准。了解这些目录结构有助于更好地管理和维护 Linux 系统。
三、树莓派Linux源码目录树分析
Linux内核源代码目录树结构
Linux是开源,免费,LInux开源社区工作者共同维护
Linux是一个开源的,支持多架构多平台代码
sudo apt-get install tree
Linux 源码目录树非常庞大,包含了操作系统的各个组件和子系统。以下是 Linux 源码目录树的主要部分和其功能的简要分析:
-
arch/:
- 包含了不同体系结构(架构)的内核代码。每个体系结构都有一个子目录,如 x86、arm、powerpc 等。
-
block/:
- 包含块设备子系统的代码,处理块设备的I/O操作。
-
crypto/:
- 提供加密算法和密码学支持的代码。
-
Documentation/:
- 包含 Linux 内核的文档,详细说明了内核的一些方面、API、参数等。
-
drivers/:
- 包含设备驱动程序的代码。每个子目录对应一类设备或子系统。
-
fs/:
- 包含文件系统的代码,包括常见的文件系统如 ext4、FAT、NTFS 等。
-
include/:
- 包含 Linux 内核的头文件,提供用户空间和内核空间的接口定义。
-
init/:
- 包含内核启动过程的初始化代码。
-
ipc/:
- 包含进程间通信(IPC)的代码,实现了共享内存、消息队列等 IPC 机制。
-
kernel/:
- 包含内核的核心代码,如调度器、定时器、信号处理等。
-
lib/:
- 包含内核和模块之间共享的一些通用库函数。
-
mm/:
- 包含内存管理子系统的代码,处理虚拟内存、物理内存等。
-
net/:
- 包含网络子系统的代码,处理网络协议栈、套接字、网络设备等。
-
scripts/:
- 包含一些用于构建和维护内核的脚本。
-
security/:
- 包含安全子系统的代码,实现了 Linux 安全模块框架。
-
sound/:
- 包含声音子系统的代码,处理音频设备和音频处理。
-
tools/:
- 包含一些辅助工具,用于内核的调试、性能分析等。
-
usr/:
- 包含用于用户空间的代码,例如 initramfs 的根文件系统。
-
virt/:
- 包含虚拟化子系统的代码,处理虚拟化和容器化。
-
Makefile:
- 根目录下的 Makefile 包含了整个内核的构建规则。
这只是 Linux 源码目录树的一小部分,整个目录树非常庞大。Linux 内核的模块化设计使得各个组件可以独立开发和维护,同时也为适应不同硬件和用途提供了灵活性。 Linux 内核的开源特性使得全球的开发者社区能够共同贡献和维护这个强大的操作系统内核。
四、树莓派Linux源码配置
在Linux系统中,源码配置通常指的是通过源码编译的方式配置和构建软件。下面是一个通用的Linux源码配置的基本流程:
-
获取源码: 首先,你需要获取你想要配置和编译的软件的源代码。这通常包括从开发者的官方网站、版本控制系统(如Git)或Linux发行版的软件仓库中获取。
-
解压源码: 如果源码是一个压缩文件(通常是.tar.gz或.zip格式),你需要解压它。你可以使用以下命令:
tar -xzvf source_code.tar.gz
或者
unzip source_code.zip
-
进入源码目录: 使用
cd
命令进入解压后的源码目录:cd source_code
-
配置: 执行
configure
脚本或其他配置脚本,该脚本通常位于源码根目录中。这个脚本会检查系统环境并生成一个Makefile,它包含了编译和安装软件的指令。如果没有configure脚本,你可能需要查看软件的文档以了解正确的配置方法。./configure
配置过程中可能需要安装一些依赖项。如果缺少某些依赖项,configure会报错,并提供相关提示。
-
编译: 执行
make
命令进行编译:make
这将根据Makefile文件编译源码,并生成可执行文件。
-
安装: 使用
make install
命令将编译好的文件安装到系统中。请注意,通常需要使用sudo
权限来进行安装:sudo make install
如果你不希望将文件安装到系统目录,而是想在当前目录下运行可执行文件,可以省略
make install
步骤。 -
清理: 如果需要,你可以使用
make clean
命令清理编译过程中生成的中间文件,或使用make distclean
清理更多文件。make clean
或者
make distclean
请注意,以上步骤是通用的,实际的配置和编译步骤可能因软件的不同而有所不同。因此,请务必阅读软件的文档以获取详细的配置和编译说明。
编写和编译驱动代码通常需要与特定内核版本兼容
驱动代码的编写
驱动代码的编译需要一个提前编译好的内核
编译内核就必须配置
配置的最终目标会生成 .config文件,该文件指导Makefile去把有用东西组织成内核
编写和编译驱动代码通常需要与特定内核版本兼容,并需要一些配置步骤。下面是一般的流程:
-
获取内核源码: 从官方Linux内核仓库、Linux发行版提供的内核源码包,或者其他可信来源获取所需的内核源码。
git clone https://github.com/torvalds/linux.git
-
配置内核: 进入内核源码目录,并运行
make menuconfig
或其他配置命令,以配置内核。这将生成一个.config
文件,其中包含了配置选项。cd linux make menuconfig
在配置中,你需要确保启用了与你的驱动相关的选项,比如设备驱动支持、文件系统支持等。你可以在
Device Drivers
下找到许多驱动相关的配置选项。 -
保存配置: 退出配置界面时,系统会询问是否保存配置,选择保存并退出。
-
编译内核: 运行
make
命令编译内核,这将生成vmlinuz
和其他必要的文件。make
-
编写驱动代码: 创建你的驱动代码文件(通常是一个
.c
文件),实现必要的功能。你的驱动代码应该包含与内核模块相关的初始化和清理函数,以及适当的模块信息。 -
编写Makefile: 创建一个Makefile文件,用于编译你的驱动代码。该Makefile通常包括编译选项和链接选项,以确保代码可以正确地与内核一起编译。
obj-m += your_driver.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
在这个例子中,
your_driver.o
是你的驱动代码的目标文件。 -
编译驱动: 运行
make
命令来编译你的驱动代码。这将生成一个.ko
文件,即内核模块。make
-
加载驱动: 使用
insmod
命令加载你的驱动模块。insmod your_driver.ko
-
查看加载信息: 使用
dmesg
命令查看内核日志,以确认驱动是否成功加载。dmesg
-
卸载驱动: 如果需要,使用
rmmod
命令卸载你的驱动模块。rmmod your_driver
这只是一个简单的示例,实际的驱动编写和编译可能会更为复杂,取决于你的具体需求和内核版本。确保阅读相关文档,并在需要时调整配置和代码。
关于Linux内核源码配置的方法
以下是对三种方式的总结:
-
使用厂家提供的配置文件:
- 方法: 将厂家提供的预配置文件(通常是
.config
)复制到内核源码目录,使用该配置进行编译。 - 优势: 简便,直接使用了厂家提供的预配置,无需逐一进行配置。
- 注意事项: 可能需要根据具体需求进行一些微调,例如添加或删除某些选项。
cp 厂家.config .config
- 方法: 将厂家提供的预配置文件(通常是
-
使用make menuconfig进行交互式配置:
- 方法: 运行
make menuconfig
命令,通过文本界面逐一选择配置选项。 - 优势: 灵活,可以根据具体需求定制内核配置。适用于需要进行详细配置的情况。
- 注意事项: 需要一定的了解和熟悉内核配置选项,可能需要花费一些时间。
make menuconfig
- 方法: 运行
-
完全自己进行配置:
- 方法: 手动编辑
.config
文件,通过文本编辑器逐一配置内核选项,包括添加、删除、修改。 - 优势: 完全定制化,可以根据需求进行精细的配置,适用于高度定制的场景。
- 注意事项: 需要对内核配置有较深的了解,不适用于初学者。配置时需要格外小心,确保不会破坏内核的基本结构。
- 方法: 手动编辑
这三种方式提供了不同的灵活性和适用性,选择哪种方式取决于具体的需求和使用场景。初学者通常可以从厂家提供的配置文件开始,然后根据需要进行微调。在深入了解内核配置的同时,逐渐可以采用更灵活的方式进行配置。
五、如何配置树莓派的Linux内核
【树莓派】内核开发 说明 下载代码 编译 替换内核
在树莓派上配置Linux内核通常包括以下步骤:
-
获取树莓派内核源码:
-
树莓派官方提供了Linux内核的源代码,你可以从官方的GitHub仓库中获取。
-
使用以下命令克隆官方的内核仓库:
git clone --depth=1 https://github.com/raspberrypi/linux
-
--depth=1
选项表示只克隆最新的一次提交,以减小下载体积。
-
-
进入内核源码目录:
cd linux
-
配置内核:
-
运行
make menuconfig
以进入内核配置界面。make ARCH=arm CROSS_COMPILE=[交叉编译器前缀] menuconfig
-
在配置界面中,选择所需的配置选项。你可以使用箭头键进行导航,使用空格键进行选择,然后按下回车键进入子菜单或确认选项。
-
-
保存配置:
- 在配置界面中,选择 “Save” 保存配置并退出。
-
编译内核:
-
运行
make
命令进行内核编译。make ARCH=arm CROSS_COMPILE=[交叉编译器前缀]
-
这一步可能需要一些时间,具体取决于你的计算机性能。
-
-
生成内核映像文件:
-
运行以下命令生成内核映像文件:
make ARCH=arm CROSS_COMPILE=[交叉编译器前缀] zImage
内核映像文件通常会生成在
arch/arm/boot/
目录下。
-
-
生成设备树文件:
-
运行以下命令生成设备树文件(*.dtb):
make ARCH=arm CROSS_COMPILE=[交叉编译器前缀] dtbs
设备树文件通常会生成在
arch/arm/boot/dts/
目录下。
-
-
安装内核映像和设备树文件到SD卡:
- 将生成的
zImage
和相关的.dtb
文件拷贝到SD卡的/boot
目录。
- 将生成的
-
更新引导配置:
-
编辑
/boot/config.txt
文件,确保引导配置正确,指向新的内核映像和设备树文件。kernel=zImage device_tree=bcm2837-rpi-3-b.dtb
根据你的树莓派型号,
.dtb
文件的名称可能会有所不同。
-
-
重启树莓派:
- 重新启动树莓派,新的内核应该生效。
这是一个基本的内核配置和编译流程。根据你的需求,你可能需要更改其他配置选项或使用其他编译目标。确保参考树莓派官方文档和内核源码中的README文件,以获取更详细的信息。
驱动两种加载方式
加载 Linux 内核模块有两种主要方式:
-
编译进内核:
- 这意味着将驱动代码编译到内核镜像中,使其成为内核的一部分。
- 你需要在内核配置中选择该驱动,然后重新编译整个内核。
- 内核编译完成后,新的内核映像(通常为
zImage
)将包含该驱动。 - 这种方式适用于那些在系统启动时就需要加载的基本驱动。
-
以模块方式加载:
- 这意味着将驱动代码编译成模块(通常为
.ko
文件),并在运行时动态加载到内核中。 - 模块可以在系统启动后通过命令行工具(如
insmod
)加载。 - 加载模块时,内核会将模块的代码添加到运行中的内核中。
- 这种方式适用于那些不需要一直驻留在内核中的驱动,而是在需要时加载的情况。
- 这意味着将驱动代码编译成模块(通常为
下面是两种方式的简要描述:
编译进内核方式:
-
在内核源码中配置该驱动,确保其被包含在编译中。
make menuconfig
-
重新编译内核。
make
-
将新的内核映像烧录到系统。
以模块方式加载:
-
编译驱动成为模块。
make modules
-
加载模块到内核。
insmod xxx.ko
-
卸载模块(如果需要)。
rmmod xxx
在实际应用中,通常会选择以模块方式加载,因为这提供了更大的灵活性。只有那些必须随着内核一起启动的基本驱动才会选择编译进内核。
*
编译进内核 zImage包含了驱动
M
模块方式生成驱动文件xxx.ko 系统启动后,通过命令inmosd xxx.ko 加载
内核配置:
配置树莓派内核的指令。
下面是对指令的详细解释:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfig
-
ARCH=arm: 指定目标体系结构为 ARM 架构。
-
CROSS_COMPILE=arm-linux-gnueabihf-: 指定交叉编译器的前缀,用于生成适用于 ARM 架构的二进制文件。在这里,
arm-linux-gnueabihf-
是一个针对硬浮点(hard-float)的交叉编译器的前缀。硬浮点指的是使用硬件浮点运算单元进行浮点运算,这通常会提高性能。 -
KERNEL=kernel7: 指定要生成的内核类型。在树莓派中,
kernel7
是用于 Raspberry Pi 2 和 Raspberry Pi 3 的内核。 -
make bcm2709_defconfig: 使用
bcm2709_defconfig
配置文件生成内核配置。bcm2709
是 Raspberry Pi 2 的代号。该配置文件包含了一组默认的配置选项,适用于 Raspberry Pi 2 和 3。
这个命令的目的是为指定的目标体系结构和硬件平台生成一个默认的内核配置。这个配置可以作为内核配置的起点,你可以在此基础上通过 make menuconfig
等命令进一步定制内核配置。
六、树莓派Linux内核编译
1、编译
编译命令用于生成树莓派内核的不同部分。
下面是对指令的详细解释:
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make -j4 zImage modules dtbs
-
ARCH=arm: 指定目标体系结构为 ARM 架构。
-
CROSS_COMPILE=arm-linux-gnueabihf-: 指定交叉编译器的前缀,用于生成适用于 ARM 架构的二进制文件。
-
KERNEL=kernel7: 指定要生成的内核类型。在树莓派中,
kernel7
是用于 Raspberry Pi 2 和 Raspberry Pi 3 的内核。 -
make -j4: 使用
-j4
参数表示并行编译,同时利用 4 个核心进行编译。这样可以加速编译过程。 -
zImage: 生成内核镜像文件,这是 Linux 内核的主要可执行文件。
-
modules: 生成内核模块,这些模块可以在运行时加载到内核中。
-
dtbs: 生成设备树二进制文件,设备树文件包含了硬件信息和配置,用于在运行时配置硬件。
这个命令的目的是通过交叉编译器为指定的目标体系结构生成内核镜像、内核模块和设备树二进制文件。-j4
的参数用于充分利用多核心进行并行编译,提高编译速度。
2、编译成功后, arch/arm/boot/ 目录下找到生成的 zImage 文件
编译成功后,看到源码树目录多了vmlinux,失败则无此文件
成功后,目标zImage镜像arch/arm/boot底下
vmlinux
是 Linux 内核的可执行文件,而 zImage
是压缩后的内核镜像。在成功编译后,你会在指定的输出目录中看到这些文件。
-
vmlinux: 这是未压缩的内核可执行文件,包含了完整的内核符号信息。通常,这个文件会生成在 Linux 内核源码树的根目录下。
-
zImage: 这是压缩后的内核镜像,用于启动树莓派。它通常位于
arch/arm/boot/
目录下。
如果编译成功,你可以在 arch/arm/boot/
目录下找到生成的 zImage
文件。这个文件是你需要烧录到树莓派SD卡的内核镜像。
请确保查看编译输出,以了解是否有任何错误消息。在编译过程中,如果有错误,它们通常会在编译输出中显示,并且可能会指导你解决问题。
3、打包zImage成树莓派可用的xxx.img
命令是用于将 zImage
打包成树莓派可用的 xxx.img
文件。这个过程通常是通过使用 mkknlimg
工具完成的。
下面是对这个命令的解释:
./scripts/mkknlimg arch/arm/boot/zImage ./kernel_new.img
-
./scripts/mkknlimg: 这是一个脚本工具,用于创建树莓派可用的内核镜像文件。
-
arch/arm/boot/zImage: 这是你之前编译生成的内核镜像文件。
-
./kernel_new.img: 这是生成的树莓派可用的内核镜像文件的输出路径和文件名。
使用这个命令会将 zImage
打包成一个树莓派可用的内核镜像文件,并命名为 kernel_new.img
。你可以将这个文件烧录到 SD 卡的相应位置,使树莓派在启动时使用这个内核。
请注意,确保你已经按照树莓派启动的相关步骤进行配置,包括在 SD 卡上的 config.txt
文件中正确指定了内核镜像的位置。
4、数据拷贝
你提供的是关于将内核和相关文件拷贝到 U 盘上以更新树莓派系统的步骤。下面是对这个操作的逐步解释:
-
创建目录:
mkdir data1 data2
创建两个目录
data1
和data2
,用于挂载 U 盘上的两个分区。 -
挂载 U 盘分区:
sudo mount /dev/sdb1 data1 sudo mount /dev/sdb2 data2
一个fat分区,是boot相关的内容,kernel的img
一个是ext4分区,也就是系统的根目录分区。
将 U 盘的第一个分区挂载到 data1
,第二个分区挂载到 data2
。这里假设 U 盘分区是 /dev/sdb1
和 /dev/sdb2
。
-
安装内核模块到 U 盘系统分区:
安装modules, 设备驱动文件:如 HDMI接口 USB WIFI I/O …sudo ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=/home/tan/data2 modules_install
将编译生成的内核模块安装到 U 盘系统分区中。这是确保 U 盘上的系统具有新的内核模块的步骤。
-
备份原内核镜像:
先备份cd /home/tan/data1 cp kernel7.img kernel7OLD.img
在
data1
目录中备份原始的内核镜像文件,以便出现问题时可以回滚。 -
拷贝新生成的内核镜像到 U 盘:
再把编译新生成的拷贝到data1,起名kernel7.imgcp kernel_new.img /home/tan/data1/kernel7.img
将新生成的内核镜像拷贝到 U 盘上,并命名为
kernel7.img
,这是树莓派所期望的内核镜像文件名。 -
拷贝设备树文件:
拷贝配置文件
复制其他相关文件cp arch/arm/boot/dts/.*dtb* /home/tan/data1 cp arch/arm/boot/dts/overlays/.*dtb* /home/tan/data1/overlays/ cp arch/arm/boot/dts/overlays/README /home/tan/data1/overlays/
将编译生成的设备树文件拷贝到 U 盘中。这些文件通常以
.dtb
结尾。
以上操作假设你的 U 盘已经正确挂载,并且文件路径和命令参数都是正确的。确保在执行这些操作之前,U 盘上的分区已经正确挂载。
七、配置启动参数的cmdline.txt
Raspberry Pi(树莓派)中用于配置启动参数的 cmdline.txt
文件的示例。在这个文件中,你可以设置一些启动时的参数,以影响系统的行为。
dwc_otg.lpm_enable=0 console=tty1 console=serial0,115200 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
让我们解释一下这个例子中的参数:
-
dwc_otg.lpm_enable=0
:dwc_otg
是 Raspberry Pi 中用于 USB 控制器的驱动程序。lpm_enable=0
表示将 USB 低功耗模式禁用。
-
console=tty1
和console=serial0,115200
:console=tty1
表示将控制台输出(终端)重定向到第一个虚拟终端。console=serial0,115200
表示将控制台输出也重定向到串口 0(Raspberry Pi 上的 UART 接口),波特率为 115200。
-
root=/dev/mmcblk0p2
:root
参数指定了根文件系统所在的设备。/dev/mmcblk0p2
表示使用 SD 卡(mmcblk0)上的第二个分区(p2)作为根文件系统。
-
rootfstype=ext4
:- 指定根文件系统的文件系统类型,这里是 ext4。
-
elevator=deadline
:elevator
参数指定了 I/O 调度器的类型,这里是使用 deadline 调度器。
-
fsck.repair=yes
:fsck.repair
参数表示在检查文件系统时自动修复任何错误。
-
rootwait
:rootwait
参数告诉内核等待根文件系统设备就绪。
这些参数可以根据系统的需求进行调整,但在大多数情况下,使用默认值是合适的。在修改 cmdline.txt
文件时,请确保你知道自己在做什么,并备份文件以防止意外。