嵌入式 Linux 开发 7:编译应用程序

简介 Linux 应用程序

从用户的角度来看,一台 Linux 产品的价值在于设备上运行的应用程序所能解决的问题。
而 Linux 得到广泛使用的一个原因是有很多开源的应用程序。

编译与部署应用程序的流程

交叉编译的 Makefile

如下所示,设计合理的 Makefile 通过执行以下 3 个命令即可调用交叉编译器:编译,清理和安装应用程序。

  • 编译 make
  • 清理 make clean
  • 安装 make install
CROSS   = arm-linux-
CC      = $(CROSS)gcc
STRIP   = $(CROSS)strip

PPPD_PATH = ./ppp-2.4.5
PPPD_EXEC = $(PPPD_PATH)/pppd

all:$(PPPD_EXEC)

.PHONY:$(PPPD_EXEC)

$(PPPD_EXEC):
        $(MAKE) -C $(PPPD_PATH) CC=$(CC) all

clean:
        make -C $(PPPD_PATH) clean

INSTALL_DIR=<install_directory>
install:$(PPPD_EXEC) ./options
        $(STRIP) $(PPPD_EXEC)
        sudo cp -f $^ ${INSTALL_DIR}

依赖库

程序库预定的位置是 /lib 如果将其放置在其他目录,这需要设定查找路径,即配置 LD_LIBRARY_PATH 环境变量。
这会迫使动态链接器到 LD_LIBRARY_PATH 指向的目录查找程序库。如同 PATH 环境变量,可以用冒号(:)隔开每个目录路径。

小窍门:
在 Linux 工作站或服务器,通常只会使用 LD_LIBRARY_PATH 暂存新程序库路径。
要永久加入一个程序库路径,这得修改 /etc/ld.so.conf 配置文件,接着使用 ldconfig 命令产生 /etc/ld.so.cache
动态链接器会依照 /etc/ld.so.cache 文件的指示找到应用程序所动态链接的程序库。

关联文件

关联文件依赖应用程序自身,一般包括:配置和日志文件。
一个良好的习惯是将关联文件写入 Makefile 的 install 目标,实现一键安装。

上电自启动

将应用程序的全路径写入 inittab 的 respawn 选项就可以实现上电自启动,参考下面的【配置 init】

BusyBox 嵌入式 Linux 命令行工具集

BusyBox 是什么

BusyBox 实现嵌入式 Linux 的命令行工具,相当于 Ubuntu/CentOS 的 Shell
它非常小巧,功能强大,易于编译和部署,是嵌入式 Linux 必不可少的基础软件。
鉴于它的广泛使用,一些社区人员称嵌入式 Linux 为 BusyBox/Linux

下载 BusyBox

一般说来 CPU 厂商会提供 BusyBox 软件包,直接使用它就好了,至少它经过验证。
如果厂商没有提供,可以从 https://busybox.net/downloads/ 下载 BusyBox 软件包。

配置 BusyBox

如果图省事,执行 make defconfig 使用默认配置就足够了。
需要精细化定制 BusyBox 执行 make menuconfig 按菜单选择需要的功能。

编译 BusyBox

首先建立 ../busybox_install 用于存储 BusyBox 生成的二进制执行文件和链接符号。
下面的命令会编译 BusyBox 并安装二进制执行文件和链接符号到指定目录(此处是 ../busybox_install)
make ARCH=arm CROSS_COMPILE=arm-nuvoton-linux-uclibceabi- CONFIG_PREFIX=../busybox_install/ install

部署 BusyBox

查询 BusyBox 链接库

下面的命令会查找 BusyBox 依赖的动态链接库,本例中它依赖 3 个库(libm=数学库,libc=C库,ld=加载库)
请确保目标板 Linux 系统有这 3 个库文件(一般存放在 /lib),否则,BusyBox 无法正常运行。
arm-nuvoton-linux-uclibceabi-ldd busybox_install/bin/busybox

checking sub-depends for 'not found'
checking sub-depends for 'not found'
        libm.so.0 => not found (0x00000000)
        libc.so.0 => not found (0x00000000)
        /lib/ld-uClibc.so.0 => /lib/ld-uClibc.so.0 (0x00000000)

拷贝 BusyBox 到根文件系统

首先删除目标板 rootfs 的 4 个目录和文件: bin/ linuxrc sbin/ usr/
然后将 busybox_install 下的 4 个同名目录和文件复制到 rootfs 之下(请给它们赋予 root 权限)。
重启目标板 Linux 就可以运行 BusyBox 了(运行 busybox --list 查看支持命令集)。

配置 init

表1 busybox init 所识得的 inittab 动作类型

动作 结果
sysinit 为 init 提供初始化命令脚本的路径
respawn 每当相应的进程终止运行,便予以重新启动
shutdown 关闭系统之前,执行相应的进程
restart 当 init 重新启动时,执行相应的进程(通常指 init 本身)

表2 busybox 使用 inittab 实例

语句 用途
::sysinit:/etc/init.d/rcS 将 /etc/init.d/rcS 设成系统的初始化文件
::respawn:/sbin/getty 115200 ttyS0 在串口 ttyS0 以 115200 波特率启动一个登录会话
::respawn:/<application_path>/exec_name 启动应用程序
::restart:/sbin/init 如果 init 重启,将 /sbin/init 设定成所要执行的程序
::shutdown:/bin/umount -a -r 关机时卸载所有文件系统,卸载失败以只读模式重新挂载

Dropbear 嵌入式 Linux 的 ssh

为了更好地维护产品,这需要添加 Linux 网络通道。相比 Telnet 孱弱的安全性,ssh 使用公钥加密法,以确保端对端通信的机密性,并且相当容易使用以及部署。

Dropbear 是什么

工作站 Linux 大多使用 OpenSSH,它依赖独立的 OpenSSL 链接库。它有 2 个弊端:交叉编译困难重重,所产生的二进制文件超过 1MB。
幸运的是,有一个供嵌入式系统使用的开放源码 SSH 服务器+客户端,它就是 Dropbear。

下载 Dropbear

wget https://matt.ucc.asn.au/dropbear/dropbear-2022.83.tar.bz2
tar jxvf ./dropbear-2022.83.tar.bz2

编译 Dropbear

CROSS   = arm-nuvoton-linux-uclibceabi-
CC      = $(CROSS)gcc
STRIP   = $(CROSS)strip
STRIP=${STRIP} CC=${CC} ./configure --host=${TARGET}
make PROGRAMS="dropbear dropbearkey scp dbclient" MULTI=1 strip

部署 Dropbear

复制 Dropbear 到根文件系统

cp -f dropbearmulti ${PRJROOT}/rootfs/usr/sbin/dropbear
ln -s ../sbin/dropbear ${PRJROOT}/rootfs/usr/bin/dropbearkey
ln -s ../sbin/dropbear ${PRJROOT}/rootfs/usr/bin/scp
ln -s ../sbin/dropbear ${PRJROOT}/rootfs/usr/bin/dbclient
ln -s ../sbin/dropbear ${PRJROOT}/rootfs/usr/bin/ssh

生成每台机器唯一的 RSA 和 DSS 密钥

RSA_KEY=/opt/dropbear_rsa_host_key
DSS_KEY=/opt/dropbear_dss_host_key

if [ ! -f $RSA_KEY ]
then
    /usr/bin/dropbearkey -t rsa -f $RSA_KEY
fi

if [ ! -f $DSS_KEY ]
then
    /usr/bin/dropbearkey -t dss -f $DSS_KEY
fi

小窍门1:此处的 /opt 是 writeable 分区
小窍门2:上述命令在第一次生成密钥时耗时比较多,小心它耽误了其他重要进程的调度(如:喂看门狗)。

上电自启动 Dropbear

添加下面的语句到 /etc/inittab 便可在引导的时候启动 dropbear。
::respawn:/usr/sbin/dropbear -r /opt/dropbear_rsa_host_key -d /opt/dropbear_dss_host_key

测试 Dropbear

  • 基于 Linux 工作站通过 ssh 登录嵌入式 Linux 系统。
  • 基于 嵌入式 Linux 系统通过 ssh 登录 Linux 工作站。
  • 基于 Linux 工作站通过 scp 从嵌入式 Linux 传送文件。
  • 基于嵌入式 Linux 通过 scp 从 Linux 工作站传送文件。

udhcpc 嵌入式 Linux 的 DHCP 客户端

在某些局域网环境仅支持 DHCP 分配 IP 地址,这就需要 Linux 目标板支持 DHCP 客户端。

udhcpc 是什么

udhcpc 是 BusyBox 项目的一部分,使用 which udhcpc 可以查看路径为 /sbin/udhcpc

部署 udhcpc

udhcpc 依赖配置文件 /usr/share/udhcpc/default.script 可以从 BusyBox 源代码中查找 simple.script 并复制。
cp -f $(find ./busybox_code/ -name simple.script) ${PRJROOT}/rootfs/usr/share/udhcpc/default.script

测试 udhcpc

执行 /sbin/udhcpc -R -p /var/run/udhcpc.eth0.pid -i eth0 -b &> /dev/null 可通过 DHCP 获取 IP 和 DNS 信息。

小窍门:
一些 Linux 目标板希望将 4G 作为【首选】路由,这需要执行 /sbin/route del default dev eth0 删除 udhcpc 的默认路由。

posted @ 2023-01-16 15:04  KevinAshton  阅读(255)  评论(0编辑  收藏  举报