学习笔记——Linux内核与嵌入式开发3

一、内核编译系统详解

1.1 Makefile系统

1.1.1 内核Makefile结构
复制代码
Linux内核源码目录结构:
arch/     - 架构相关代码
drivers/  - 设备驱动
fs/       - 文件系统
include/  - 头文件
init/     - 初始化代码
kernel/   - 核心内核
mm/       - 内存管理
net/      - 网络协议
1.1.2 配置变量系统

Makefile中的配置变量

复制代码
# 示例:drivers/char/Makefile中的配置
obj-$(CONFIG_MAIN) += main.o
obj-$(CONFIG_FUN1_MEMORY) += fun1.o
obj-$(CONFIG_FUN2_NET) += fun2.o

# 链接规则
$(TARGET): $(OBJ)
    gcc $^ -o $@

变量说明

  • obj-y:编译进内核(built-in)

  • obj-m:编译为模块(module)

  • obj-n:不编译

  • obj-:总是编译(无条件)

.config文件示例

复制代码
CONFIG_MAIN=y
CONFIG_FUN1_MEMORY=y
CONFIG_FUN2_NET=y
CONFIG_DEMO_DRIVER=m
1.1.3 自动变量
复制代码
$@ - 目标文件名
$< - 第一个依赖文件名
$^ - 所有依赖文件
$? - 比目标新的依赖文件
$* - 不包含扩展名的目标文件

1.2 内核编译流程

1.2.1 完整编译步骤

所有命令均在Linux内核源码的顶层目录执行

步骤1:获取内核源码

复制代码
# 拷贝内核源码压缩包到Ubuntu
# 假设文件名为:linux-4.1.15.tar.xz

步骤2:解压内核源码

复制代码
sudo tar -xvf linux-4.1.15.tar.xz

# 修改源码目录权限(建议)
sudo chmod 0777 linux-4.1.15 -R
# 或
sudo chown -R $(whoami):$(whoami) linux-4.1.15

步骤3:应用默认配置

复制代码
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig

命令参数说明

  • ARCH=arm:指定ARM架构

  • CROSS_COMPILE=arm-linux-gnueabihf-:指定交叉编译器前缀

  • imx_alientek_emmc_defconfig:i.MX6开发板的默认配置文件

步骤4:配置内核模块

复制代码
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

menuconfig界面操作

复制代码
键盘操作:
↑↓       - 上下移动
Enter    - 进入子菜单/确认选择
Y        - 编译进内核
M        - 编译为模块
N        - 不编译
/        - 搜索配置项
?        - 查看帮助
ESC ESC  - 返回/退出

步骤5:编译内核

复制代码
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16

参数说明

  • all:编译所有内容(zImage、模块、设备树)

  • -j16:使用16个线程并行编译(根据CPU核心数调整)

步骤6:获取编译结果

复制代码
# 内核镜像位置
arch/arm/boot/zImage

# 设备树文件位置
arch/arm/boot/dts/*.dtb

# 内核模块位置
各个驱动目录下的*.ko文件

步骤7:部署验证

复制代码
# 拷贝到TFTP服务目录
cp arch/arm/boot/zImage /tftpboot/
cp arch/arm/boot/dts/imx6ull-alientek-emmc.dtb /tftpboot/imx6.dtb

1.3 内核镜像格式

1.3.1 三种内核镜像

1. Image

  • 原始的内核镜像

  • 未经压缩,可以直接执行

  • 文件最大

  • 位置:arch/arm/boot/Image

2. zImage

  • 压缩的内核镜像

  • 结构:解压程序 + 压缩的Image

  • 最常用格式

  • 位置:arch/arm/boot/zImage

3. uImage

  • U-Boot专用的内核镜像

  • 结构:64字节的头信息 + zImage

  • 包含加载地址、入口地址等信息

  • 位置:arch/arm/boot/uImage

1.3.2 镜像生成关系
复制代码
vmlinux(ELF格式) → Image(原始二进制) → zImage(压缩) → uImage(U-Boot格式)

1.4 Kconfig配置系统

1.4.1 Kconfig作用
  • 定义make menuconfig中的配置选项

  • 管理内核功能模块的编译选项

  • 生成.config配置文件

1.4.2 Kconfig语法

基本语法元素

复制代码
config SYMBOL          # 配置选项
    bool "描述"        # 布尔类型选项
    default y          # 默认值
    depends on XXX     # 依赖关系
    select YYY         # 反向依赖
    help               # 帮助信息
      详细的帮助说明

常见类型

  • bool:布尔类型(y/n)

  • tristate:三态(y/m/n)

  • int:整数类型

  • string:字符串类型

  • hex:十六进制数

1.4.3 Kconfig示例
复制代码
config DEMO_DRIVER
    tristate "Demo driver support"
    default n
    help
      This is a demo driver for learning.
      Say Y to compile it into the kernel.
      Say M to compile it as a module.

1.5 向内核添加新文件

1.5.1 添加驱动文件步骤

以向drivers/char目录添加demo.c为例

步骤1:创建驱动源文件

复制代码
// drivers/char/demo.c
#include <linux/module.h>
#include <linux/init.h>

static int __init demo_init(void)
{
    printk(KERN_INFO "Demo driver loaded\n");
    return 0;
}

static void __exit demo_exit(void)
{
    printk(KERN_INFO "Demo driver removed\n");
}

module_init(demo_init);
module_exit(demo_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Your Name");
MODULE_DESCRIPTION("A simple demo driver");

步骤2:修改Makefile

复制代码
# drivers/char/Makefile
# 在适当位置添加:
obj-$(CONFIG_DEMO) += demo.o

步骤3:修改Kconfig

复制代码
# drivers/char/Kconfig
# 在适当位置添加:
config DEMO
    bool "Demo driver support"
    default n
    help
      This is a simple demo driver for learning kernel programming.
      If unsure, say N.

步骤4:配置内核

复制代码
# 进入配置界面
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig

# 导航到:
# Device Drivers → Character devices → Demo driver support
# 按Y或M选择编译方式

步骤5:编译内核

复制代码
# 如果编译进内核(Y)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage

# 如果编译为模块(M)
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules

# 模块文件位置
# drivers/char/demo.ko

二、交叉编译工具链

2.1 工具链组成

2.1.1 主要工具
复制代码
arm-linux-gnueabihf-gcc      - C编译器
arm-linux-gnueabihf-g++      - C++编译器
arm-linux-gnueabihf-ld       - 链接器
arm-linux-gnueabihf-objcopy  - 目标文件转换
arm-linux-gnueabihf-objdump  - 目标文件反汇编
arm-linux-gnueabihf-readelf  - ELF文件查看
arm-linux-gnueabihf-strip    - 去除调试信息
2.1.2 工具链命名规则
复制代码
arm-linux-gnueabihf-
├── arm        - 目标架构(ARM)
├── linux      - 目标系统(Linux)
├── gnueabi    - GNU EABI(嵌入式应用二进制接口)
└── hf         - 硬浮点(Hard Float)

2.2 交叉编译使用

2.2.1 编译应用程序
复制代码
# 编译C程序
arm-linux-gnueabihf-gcc -o hello hello.c

# 带优化选项
arm-linux-gnueabihf-gcc -O2 -o app main.c

# 静态链接
arm-linux-gnueabihf-gcc -static -o app_static main.c
2.2.2 编译内核模块
复制代码
# 需要指定内核路径
make -C /path/to/kernel M=$(pwd) modules

# 或在内核源码目录编译
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules

三、开发板与主机通信

3.1 网络配置

3.1.1 静态IP配置

开发板端

复制代码
# 临时设置
ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up

# 永久设置(修改配置文件)
# /etc/network/interfaces
auto eth0
iface eth0 inet static
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1

Ubuntu主机

复制代码
# 设置静态IP
sudo vim /etc/netplan/01-network-manager-all.yaml

# 内容示例
network:
  version: 2
  ethernets:
    enp3s0:
      addresses: [192.168.1.3/24]
      gateway4: 192.168.1.1
      nameservers:
        addresses: [8.8.8.8, 8.8.4.4]
3.1.2 网络测试
复制代码
# 开发板ping主机
ping 192.168.1.3

# 主机ping开发板
ping 192.168.1.100

# 查看网络接口
ifconfig
或
ip addr show

四、常见问题解决

4.1 编译问题

4.1.1 编译器找不到
复制代码
问题:arm-linux-gnueabihf-gcc: command not found
解决:
sudo apt install gcc-arm-linux-gnueabihf
4.1.2 头文件缺失
复制代码
问题:fatal error: xxx.h: No such file or directory
解决:
# 安装开发包
sudo apt install libxxx-dev

# 或指定包含路径
arm-linux-gnueabihf-gcc -I/path/to/include -o app app.c

4.2 运行问题

4.2.1 动态库缺失
复制代码
问题:./app: error while loading shared libraries: libxxx.so: cannot open shared object file
解决:
# 在开发板安装库文件
# 或静态链接
arm-linux-gnueabihf-gcc -static -o app app.c
4.2.2 权限问题
复制代码
问题:Permission denied
解决:
# 添加执行权限
chmod +x app

# 或使用root权限
sudo ./app
相关推荐
怎么没有名字注册了啊2 小时前
C++ 进制转换
开发语言·c++
觉醒大王2 小时前
硕士/博士研究生避坑指南
笔记·深度学习·学习·自然语言处理·职场和发展·学习方法
代码游侠2 小时前
C语言核心概念复习(二)
c语言·开发语言·数据结构·笔记·学习·算法
Gain_chance2 小时前
31-学习笔记尚硅谷数仓搭建-DWD层工具域优惠券使用(支付)、互动域收藏商品、流量域页面浏览、用户域用户注册、用户域用户登录事务事实表建表语句及分析
笔记·学习
冰暮流星2 小时前
javascript之双重循环
开发语言·前端·javascript
金枪不摆鳍2 小时前
C++常用关键字考察
c++
墨月白2 小时前
[QT]QProcess的相关使用
android·开发语言·qt
小小码农Come on2 小时前
QT信号槽机制原理
开发语言·qt
KoiHeng2 小时前
Java的文件知识与IO操作
java·开发语言