一.内核源码树
- Linux内核源码有上万个文件,有上千万多行的代码
- Linux有是一个开源的,支持多架构多平台的代码,内容庞大
- 由于Linux内核源码的内容冗杂,所以在使用之前,需要裁剪出我们需要的内容,重新编译
- 进入目标目录下,可以用tree查看源码数目录
二.源码树目录结构
2.1Linux内核源码的整体分布情况:现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序和网络等组成。
-
arch 目录:包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此目录。
-
block:块设备驱动程序
-
crypto:常用加密和离散算法(如AES,SHA等),还有一些压缩和CRC校验算法
-
include 目录:包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下。
-
init 目录:包含核心的初始化代码(不是系统的引导代码),有main.c和Version.c两个文件。这是研究核心如何工作的好起点。
-
mm 目录:包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下。
-
drivers 目录:中是系统中所有的设备驱动程序。它又进一步划分成几类设备驱动,每一种有对应的子目录,如声卡的驱动对应于drivers/sound。
-
ipc 目录:包含了核心进程间的通信代码。
-
modules 目录:存放了已建好的、可动态加载的模块。
-
fs 目录:存放Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext3文件系统对应的就是ext3子目录。
-
Kernel :内核管理的核心代码放在这里。同时与处理器结构相关代码都放在arch/*/kernel目录下。
-
net 目录:里是核心的网络部分代码,其每个子目录对应于网络的一个方面。
-
lib 目录:包含了核心的库代码,不过与处理器结构相关的库代码被放在arch/*/lib/目录下。
-
scripts 目录:包含用于配置核心的脚本文件。
-
documentation 目录:下是一些文档,是对每个目录作用的具体说明。
2.2一般在每个目录下都有一个.config文件和一个Makefile文件。
- 这两个文件都是编译时使用的辅助文件。仔细阅读这两个文件对弄清各个文件之间的联系和依托关系很有帮助。另外有的目录下还有Readme文件,它是对该目录下文件的一些说明,同样有利于对内核源码的理解。
三. Linux内核源码的配置
3.1为什么要配置?
- 驱动代码的编译需要一个提前编译好的内核,而内核根据功能需求不同而进行配置,配置的结果就是生成一个.config文件,.config文件用于指导 Makefile 去吧有用的东西组织生成内核。
3.2配置方式
- 通常厂家会提供配置好的内核源码,会有一个厂家.config
3.2.2方式一
- cp 厂家.config .config
3.2.3方式二
- make menuconfig 一项项配置,通常是基于厂家的config来配置
3.2.3方式三
- 完全自己来
3.3具体配置步骤
-
方式一:直接使用厂家的config文件配置
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make bcm2709_defconfigARCH=arm: 指定arm架构 CROSS_COMPILE=arm-linux-gnueabihf- : 指定编译器 KERNEL=kernel7: 树莓派 make bcm2709_defconfig: 主要核心命令
-
方式二:通过menuconfig的nucurse界面一项项配置
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-KERNEL=kernel7 make menuconfig界面中的*表示要植入的部分,空白表示忽略, Device Drivers 驱动部分:M表示以模块的方式加载,Y或星号表示直接编译进内核
四.内核编译
-
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-KERNEL=kernel7 make -j4 zImage modules dtbs
-j4:指定用多少电脑资源进行编译
zImage:生成内核镜像
modules:要生成驱动模块
dtbs:生成配置文件 -
编译成功会在源码树目录下生成没有压缩的vmlinux和vmlinux.o,它真正的内核生成在/arch/arm/boot目录下,里面有bootp compressed dts Image install.sh Makefile zImage等,zImage想要的目标镜像。
-
把生成的zImage打包成kernel_new.img,这里就用到了scripts目录下的脚本文件,先回到源码树目录下:
./scripts/mkknlimg arch/arm/boot/zImage kernel_new.img
五.挂载U盘
- 把sd卡插入读卡器,连到虚拟机
- dmesg命令可以查看到内核的打印信息,看到sd1,sd2挂载到了虚拟机上
- 树莓派sd卡有两个分区:sdb1是fat分区,用来放boot相关内容,kernel的img文件就放在这;sdb2是ext4分区,就是根目录分区。
- mkdir data1 data2 :创建两个文件夹到工作目录下,用于挂载sdb1,sdb2;sdb1和sdb2位于/dev/目录下;
- 挂载: sudo mount dev/sdb1 data1
sudo mount dev/sdb2 data2
六.安装modules(设备驱动文件)
- 到源码树目录下
ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- KERNEL=kernel7 make INSTALL_MOD_PATH=[ext4分区所挂载的目录] modules_install
七.安装更新sdb1里面的kenel.img文件
- 为了防止意外,内核裁剪失败,导致内核无法启动,可以先备份data1中原有的kernel.img
cp kernel7.img kernel7OLD.img - 将kernel_new.img拷贝到data1,覆盖掉kenel7.img
cp kernel_new.img ~/data1/kernel7.img - 可以用md5sum 验证文件是否拷贝成功
八.更新配置文件
1. cp arch/arm/boot/dts/.*dtb* ~/data1
2. cp arch/arm/boot/dts/overlays/.*dtb* ~/data1/overlays/
3. cp arch/arm/boot/dts/overlays/README ~/data1/overlays/