欢迎来到系统移植的第三篇文章本文详细介绍了Linux内核的编译、裁剪与启动流程。主要内容包括1. 内核概念与职责包括进程管理、内存管理等功能2. 内核编译流程详解从获取源码到生成镜像文件3. 内核裁剪方法通过menuconfig移除不需要的模块4. 完整的启动流程分析从uboot跳转到内核初始化5. 内核与用户空间的交互方式6. 内核调试技巧及常见问题解决方法。文章以I.MX6ULL开发板为例提供了实用的操作指南和注意事项适合嵌入式开发者参考。一、内核1.什么是内核1内核Kernel是操作系统的核心部分负责管理计算机的硬件资源并为上层应用程序提供运行环境。可以把它理解为“硬件与软件之间的翻译官”或“资源大管家”。2内核的职责职责说明进程管理创建、调度、终止进程决定哪个程序占用 CPU、运行多久如 CFS 调度算法内存管理分配和回收内存通过虚拟地址空间MMU让每个进程以为自己独占全部内存文件系统管理管理磁盘/Flash 上的文件和目录提供统一的文件操作接口open、read、write设备驱动控制硬件外设串口、网卡、USB、GPIO 等为上层提供标准化访问方式网络管理处理网络协议栈TCP/IP收发网络数据包2.内核版本与来源在 I.MX6ULL 开发板上我使用的 Linux 内核版本是4.1.15。这个版本由 NXP 官方针对 I.MX6ULL 进行适配和优化正点原子等厂商在其基础上做了进一步的驱动开发和配置最终提供给开发者。内核源码可以从以下途径获得厂商NXP官网下载开发板厂商如正点原子提供的资料包老师或公司提供的代码仓库内核源码是开源的遵循 GPL 协议我们可以在遵守协议的前提下自由使用和修改。uname -r //查询内核版本二、内核编译流程详解编译内核之前请确保已安装交叉编译工具链第一篇内容并配置好 PATH。步骤1获取并解压内核源码tar -xjf linux-4.1.15.tar.bz2cd linux-4.1.15步骤2配置内核厂商通常会提供一个默认配置文件defconfig用于生成适合该开发板的.config文件。make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- imx_alientek_emmc_defconfig或者将厂家提供的配置文件拷贝为.config驱动选项默认配置文件中cp arch/arm/configs/imx_alientek_emmc_defconfig .config步骤3编译内核镜像make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- zImage -j4如果在对应内核源码的顶层Makefile中已经通过?为这两个变量设置了默认值ARCH ? armCROSS_COMPILE ? arm-linux-gnueabihf-就只需直接make zImage即可。当然如果换一个没有预设这些变量的内核源码我会手动加上它们或者通过export环境变量来指定。步骤4编译设备树dtb生成的文件位于arch/arm/boot/dts/imx6ull-alientek-emmc.dtbmake ARCHarm CROSS_COMPILEarm-linux-gnueabihf- imx6ull-alientek-emmc.dtb步骤5准备 tftp 共享目录将zImage和dtb文件拷贝到 Ubuntu 的 tftp 共享目录如/var/tftp或自定义目录以便开发板通过tftp命令下载。cp arch/arm/boot/zImage /var/tftp/cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /var/tftp/三、内核裁剪1为什么需要裁剪减少内核镜像zImage的体积节省存储空间尤其是 Flash 有限的设备移除无用的驱动加快内核启动速度避免与后续自己编写的驱动产生冲突例如 LED、KEY 驱动2实际操作make ARCHarm CROSS_COMPILEarm-linux-gnueabihf- menuconfig通过图形化菜单找到需要裁剪的模块按N键将其排除或取消*号。3.常见裁剪项移除内核自带的 LED 驱动Device Drivers → LED Support → 取消选择移除按键驱动Device Drivers → Input device support → 取消不需要的按键驱动移除无用的文件系统、网络协议、调试选项等修改完成后保存退出.config文件会被更新。然后重新编译内核make zImage四、内核启动流程从 uboot 跳转开始1.Uboot:内核启动前通过uboot完成硬件、软件的初始化将内核从emmc搬移到内存并完成向内核的传参引导内核启动。2.kernel1解压内核映像跳转到解压后的内核入口点。2执行init目录下main.c中的start_kernel函数完成对内核的初始化①完成对设备树的解析②初始化控制台设置内核的打印机之以便后续的输出可以显示出来。③初始化内存管理子系统建立初始的内存管理结构准备好内存分配机制。④启动中断和处理机制设置和启动中断处理机制使得内核可以响应硬件中断。⑤初始化内核调度器初始化内核调度器以便管理进程调度。⑥加载初始进程内核创建并启动第一个用户空间进程3.rootfs挂载根文件系统内核启动后挂载的第一个文件系统挂载的目的是因为内核只提供了运行环境和系统调用所以用户态的程序和库都必须从根文件读取4.init内核 执行第一个用户空间程序通常是/linuxrc或/sbin/init。此后内核线程“退居后台”进程调度和管理由 init 进程负责系统进入用户态。五、内核与用户空间的交互方式1系统调用System Call应用程序调用open()、read()、write()、ioctl()等 C 库函数触发软中断如swi进入内核态执行相应驱动或内核函数。2mmap 内存映射将内核空间的物理内存映射到用户空间用户程序可以直接读写例如 framebuffer、寄存器区域效率高。3copy_to_user / copy_from_user驱动程序在内核态通过这两个函数安全地在用户空间和内核空间之间拷贝数据。六、内核调试与常见问题1.查看内核日志dmesgdmesg | tail -20 # 查看最后20条内核日志 dmesg -c # 清除日志缓冲区内核启动时的打印信息如硬件检测、驱动加载、挂载文件系统等都可以通过dmesg查看。2.内核恐慌Kernel Panic当内核遇到无法恢复的致命错误时会停止运行并打印Kernel panic信息。常见原因驱动不兼容编译进内核的驱动与当前硬件冲突内核无法正确管理硬件设备应用程序或者脚本进行错误的系统调用内核陷入无法处理的状态设备树错误硬件资源描述错误导致内核无法正确初始化外设根文件系统挂载失败root参数错误或 NFS 服务未就绪内存越界内核代码或驱动破坏了关键数据结构遇到内核恐慌时仔细查看最后的打印信息通常能定位到具体函数或文件。七. 补充vmlinux、Image、zImage、uImage 的区别文件说明vmlinux内核编译生成的原始 ELF 文件未压缩含有调试符号体积大一般用于调试Image从 vmlinux 中提取的纯二进制内核未压缩zImage对 Image 进行 压缩并在前面加上自解压代码体积小是常用格式uImage在 zImage 前面加上一个 64 字节的 U-Boot 头包含内核类型、加载地址、大小等U-Boot 可以直接识别在bootz命令中使用的是zImage不是 uImage。bootz专门用于启动 zImage。