imx6ull(2)

1、Buildroot 是干什么的?

一个 "一键生成好"嵌入式Linux系统的工具。

  • 输入 :一个配置文件 (比如 100ask_imx6ull_defconfig)。

  • 处理 :它自动去官方网站下载你指定的U-boot、Linux内核、各种APP (如 sshd, alsa-utils) 的源码,然后自动打补丁、配置、交叉编译。

  • 输出:三个可以直接烧录到开发板的成品:

    1. u-boot.imx (引导程序)
    2. zImage (Linux内核)
    3. rootfs.tar (根文件系统,包含 /bin, /etc, /lib 等)

一句话:你告诉它板子型号,它就能自动编译出完整的系统镜像。

1.1 与当前工作流程的对比

功能 目前在做 (手动) Buildroot 的做法 (自动)
编译 U-boot 进入U-boot目录,执行 make 命令手动编译。 自动下载、配置、编译。
编译 Kernel 进入Kernel目录,执行 make zImage 和 make modules。 自动下载、配置、编译。
制作根文件系统 (最复杂的部分) :需要手动下载 Busybox,编译,创建 /dev, /proc 等目录,配置 inittab 等。 自动完成:自动编译 Busybox,自动创建目录结构,生成完整的文件系统镜像。
管理依赖库 手动下载 libpng, zlib 等库,手动交叉编译。 自动解决依赖 (选中某个APP,会自动选中它所需的库)。

1.2、 从零构建完整系统的大致步骤

从一个空白的 Ubuntu 环境 开始,用 Buildroot 工具,生成一个可以直接在开发板上运行的全功能 Linux 系统。步骤大致如下:

第一步:获取 Buildroot 源码

bash 复制代码
git clone https://e.coding.net/weidongshan/buildroot.git
cd buildroot

第二步:配置开发板

Buildroot 支持数不清的板子,配置文件在 configs/ 目录下。

bash 复制代码
# 例如,为你的 100ask_imx6ull 开发板进行配置
make 100ask_imx6ull_defconfig

这步Buildroot会生成一个 .config 文件,告诉他"目标板是100ask的6ull"。

第三步:定制内容

这一步是可选的,也挺重要,可以打开图形化界面微调:

go 复制代码
make menuconfig

在这里可以:

  • Target packages :选择要把哪些应用编译进系统(例如,选上 python3, openssh, alsa-utils 等)。
  • Filesystem images :选择最终生成文件系统的格式,比如 tar 压缩包,或者直接生成可以烧录到 SD 卡的 ext4 镜像。

第四步:一键自动编译

这是最关键的一步,执行这个命令后:

go 复制代码
make

Buildroot 在后台会自动化完成以下所有工作:

  1. 检查工具链:如果没有,它会自动下载并编译一个合适的交叉编译工具链。
  2. 下载源码:它会自动从官网下载 U-boot、Linux Kernel、Busybox 以及你选中的所有APP的源码。
  3. 编译:自动交叉编译 U-boot、Kernel、所有APP和库。
  4. 构建根文件系统 :自动创建 bin, sbin, etc, usr 等目录,将编译好的命令和库文件放到正确的位置。
  5. 生成镜像 :最终在 output/images/ 目录下,生成你需要的所有文件。

第五步:烧录到开发板

最终,可以直接从 output/images/ 目录下获取三个文件:

  1. u-boot-dtb.imx :使用我们在 6.2.2 章节学到的方法(dd 命令)烧录到 SD 卡或 EMMC。
  2. zImage 和 .dtb 文件 :使用 5.4 章节学到的方法,复制到 /boot 分区。
  3. rootfs.tar:将其解压到你的根文件系统分区。

2、NFS挂载文件流程

简单来说,NFS(Network File System,网络文件系统)可以让你在开发板上,通过网络直接访问和使用你 Ubuntu 虚拟机里的一个指定文件夹,就像访问开发板自身存储空间一样方便。

这个过程的核心,是把 Ubuntu 的一个目录通过网络"分享"出去,然后在开发板上把这个网络位置"挂载"到自己的一个空目录下,两者就神奇的"连接"起来了。这种方式在嵌入式开发中非常常用,尤其适合调试程序,因为它省去了反复烧写的繁琐流程。

把这个过程拆解为下面几步:

第一步:让 Ubuntu 和开发板"网上"互通

NFS 基于网络,所以 Ubuntu 虚拟机与开发板必须能够互相通信。它们通常通过网线连接到同一个路由器或交换机,从而处于同一个局域网段。

最关键的一步是设置虚拟机的网络模式。你需要将 VMware 或 VirtualBox 的网络适配器设置为 "桥接模式" 。这样,你的虚拟机就会和你的 Windows 电脑一样,从路由器获取一个独立的 IP 地址,并与开发板处于同一网络层面。

接着就可以进行网络测试了:

  1. 在 Ubuntu 终端输入 ifconfig,查看其 IP 地址(例如 192.168.1.10)。
  2. 在开发板的串口终端输入 ifconfig,查看其 IP 地址(例如 192.168.1.20)。
  3. 互相 ping 一下测试连通性:
    • 在 Ubuntu 上:ping 192.168.1.20。
    • 在开发板上:ping 192.168.1.10。 如果 ping 通,说明网络连接成功。

第二步:配置 Ubuntu 作为 NFS"服务器"

Ubuntu 作为服务器,需要安装并配置 NFS 服务,来决定哪个文件夹可以被分享。

  1. 安装 NFS 服务器:在 Ubuntu 终端执行:

    bash 复制代码
    sudo apt-get install nfs-kernel-server
  2. 创建一个共享目录:这个目录就是用来存放你希望开发板访问的文件的。例如:

    bash 复制代码
    mkdir /home/book/nfs_share
  3. 配置 NFS 导出目录 :这是关键步骤。需要通过修改配置文件 /etc/exports,来告诉 NFS 服务器哪个目录可以被谁访问。编辑文件:

    bash 复制代码
    sudo vi /etc/exports

    在文件末尾添加一行,格式如下: /home/book/nfs_share *(rw,sync,no_root_squash) 参数解析:

    • /home/book/nfs_share:是你刚创建的共享目录的路径。
    • *:代表允许所有IP地址 的客户端访问。你也可以指定一个网段,如 192.168.1.0/24。
    • rw:表示客户端对该目录有**读写(Read-Write)**权限。
    • sync:数据同步写入内存和硬盘,保证数据安全。
    • no_root_squash:允许开发板上的 root 用户保留 root 权限访问共享目录,方便文件操作。
  4. 重启 NFS 服务:使配置生效:

    bash 复制代码
    sudo /etc/init.d/nfs-kernel-server restart

第三步:让开发板"挂载"共享文件夹

在开发板上安装 NFS 客户端并进行挂载。

  1. 安装 NFS 客户端(通常开发板系统已集成,如果未安装则执行):

    bash 复制代码
    sudo apt install nfs-common -y
  2. 创建一个挂载点:在开发板上创建一个空目录,作为访问 Ubuntu 共享文件夹的入口。

    bash 复制代码
    mkdir /mnt/nfs
  3. 执行挂载命令:将 Ubuntu 的共享文件夹挂载到刚刚创建的目录上。

    bash 复制代码
    mount -t nfs -o nolock 192.168.1.10:/home/book/nfs_share /mnt/nfs

    命令解析:

    • -t nfs:指定挂载的文件系统类型为 NFS。
    • -o nolock:一个常用选项,用于解决某些环境下的锁问题。
    • 192.168.1.10:你的 Ubuntu 虚拟机的 IP 地址。
    • /home/book/nfs_share:Ubuntu 上配置的共享目录 ,注意 IP 后紧跟一个冒号:。
    • /mnt/nfs:开发板上的挂载点。

挂载成功后,就可以自由地"穿梭"在两个系统之间了,下面是更具体的验证和操作方式。

如何验证 NFS 挂载成功?

挂载命令执行后,如果没有报错,通常就是成功了。可以按以下步骤测试:

  1. 在 Ubuntu 中创建文件 :进入 Ubuntu 的共享目录 nfs_share,新建一个测试文件。

    bash 复制代码
    cd /home/book/nfs_share
    touch test.txt
  2. 在开发板上查看 :在开发板的挂载点 /mnt/nfs 下,你应该能立刻看到刚才创建的 test.txt 文件。

    bash 复制代码
    ls /mnt/nfs

你也可以反向操作:在开发板的 /mnt/nfs 目录下创建一个文件,然后去 Ubuntu 的 nfs_share 目录下查看,效果是一样的。

3、gcc流程

3.1流程

阶段 命令示例 产出 作用
预处理 gcc -E main.c -o main.i .i 文件 展开宏、头文件
编译 gcc -S main.i -o main.S .S 汇编文件 生成汇编代码
汇编 gcc -c main.S -o main.o .o 目标文件 生成机器码(未链接)
链接 gcc -o test main.o sub.o 可执行文件 合并 + 符号解析 + 重定位

3.2 链接器

链接 = 把多个 .o 目标文件和库"拼"成一个完整的可执行文件

css 复制代码
# 多文件直接链接(最简单)
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c
gcc -o test main.o sub.o          # main.o + sub.o 直接合成 test

3.3 静态库 vs 动态库

特性 静态库 .a 动态库 .so
链接时机 链接期间 编译时记录依赖,运行时加载
是否复制代码 是,复制到可执行文件中 否,只记录需要哪个库
可执行文件大小 大 小
内存占用 每个程序各有一份拷贝 多程序共享同一份 .so 内存
库更新 需重新链接整个程序 替换 .so 文件即可(接口不变时)
运行时依赖 无 必须能找到 .so 文件
适用场景 小项目、独立部署 多程序共用、节省存储/内存

3.3.1 静态库制作与使用

bash 复制代码
# 1. 生成目标文件
gcc -c -o main.o main.c
gcc -c -o sub.o sub.c

# 2. 打包成静态库(ar = archive)
ar rcs libsub.a sub.o

# 3. 使用静态库链接
gcc -o test main.o -L. -lsub
# 或直接写文件名
gcc -o test main.o libsub.a

3.3.2 动态库制作与使用

bash 复制代码
# 1. 生成目标文件(位置无关代码 -fPIC 通常推荐加)
gcc -c -fPIC -o main.o main.c
gcc -c -fPIC -o sub.o sub.c

# 2. 生成动态库(-shared)
gcc -shared -o libsub.so sub.o

# 3. 使用动态库链接
gcc -o test main.o -L. -lsub

# 4. 运行时让系统找到动态库
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
./test

-lname 对应查找 libname.so(动态库)或 libname.a(静态库)

-l 参数 对应的库文件
-lsub libsub.so 或 libsub.a
-lm libm.so(数学库)
-lpthread libpthread.so(线程库)
-lxxx libxxx.so 或 libxxx.a

规律 :-l 后面跟的名字会被自动加上 lib 前缀和 .so/.a 后缀

3.4 链接时库的搜索顺序

3.4.1 编译时(链接器查找库)

  1. -L 指定的目录
  2. 环境变量 LIBRARY_PATH
  3. 系统默认目录(/lib、/usr/lib、/usr/local/lib)
bash 复制代码
gcc -o test main.o -lsub -L/home/book/mylibs -L.

3.4.2 运行时(动态链接器查找 .so)

  1. 环境变量 LD_LIBRARY_PATH
  2. 配置文件 /etc/ld.so.conf 中的目录
  3. 系统默认目录(/lib、/usr/lib)
ruby 复制代码
# 临时添加搜索路径
export LD_LIBRARY_PATH=$LD_LIBRASRY_PATH:/my/lib/path

# 永久添加(需要 root)
sudo sh -c "echo '/my/lib/path' > /etc/ld.so.conf.d/mylib.conf"
sudo ldconfig
相关推荐
树下水月6 分钟前
Typora破解
linux·服务器·前端
沫璃染墨39 分钟前
《从零入门Linux系统篇(五十七):线程篇·十——生产者消费者模型进阶:从环形缓冲区到POSIX信号量》
linux·运维·服务器·开发语言·c++·系统架构·信号处理
wuminyu1 小时前
LockStack在虚拟线程Mount和Unmount拷贝过程剖析
java·linux·c语言·jvm·c++
深念Y1 小时前
rime-雾凇拼音-配置记录
linux·junit·软件·拼音·kde
殷色玫瑰2 小时前
C++ string类详解:常用接口、字符串操作与模拟实现
java·linux·c语言·开发语言·数据结构·c++
忆挽篱笙歌3 小时前
gcc,g++
linux
l1t3 小时前
修复WSL CreateInstance/E_UNEXPECTED和 mounted read-only 错误
linux·windows·wsl
Ruiery4 小时前
Linux 6.6内核 CPU 深度解析(九):时钟与 TSC — 内核怎么从 PIT/HPET 切到 TSC
linux·运维·服务器
91刘仁德4 小时前
Linux网络编程从入门到实战:UDP/TCP协议与socket编程全解析
linux·网络·笔记·tcp/ip·udp
水饺编程5 小时前
第1章:下载 Linux 0.12 内核
linux·c语言·汇编·ubuntu