嵌入式开发:Yocto插件安装、BusyBox配置与用户空间初始化
1. Yocto插件安装
在进行开发时,我们可能需要安装一些必要的工具和插件,Yocto插件就是其中之一。以下是安装Yocto插件的详细步骤:
1.
安装C/C11开发工具SDK
:
- 展开“Programming Languages”,选择“C/C11 Development Tools SDK”。
- 连续点击“Next”两次,接受许可条款,然后点击“Finish”。此时会提示重启Eclipse使更改生效,但先不要重启,因为接下来要安装Yocto插件。
2.
安装Yocto插件
:
- 回到“Install New Software”界面,在“Work with”区域点击“Add…”。
- 在“Location”字段中输入
http://downloads.yoctoproject.org/releases/eclipse-plugin/2.3/neon
,并在“Name”字段中提供有意义的名称,然后点击“OK”。
- 勾选出现的两个条目,连续点击“Next”两次,接受许可,点击“Finish”。此时会弹出安全警告,提示软件未签名且无法确定其真实性,点击“OK”继续。
3.
重启Eclipse
:安装完成后,重启Eclipse,你会发现新增了“Yocto Project Tools”菜单选项,并且在“Window - Preferences”中有“Yocto Project SDK”对话框。
个人观察
Yocto相较于OE - Core可能有所改进,至少它有一些图形化工具。然而,和OE - Core一样,它体积庞大、复杂度高,学习曲线较陡。如果愿意投入时间深入学习,它可能会很有用。
相关资源
| 资源名称 | 网址 |
|---|---|
| Buildroot项目 | www.buildroot.org |
| Open Embedded项目 | www.openembedded.org |
| Yocto项目 | www.yoctoproject.org |
| Yocto项目下载页面 | http://downloads.yoctoproject.org |
| Python官网 | www.python.org |
| Open Embedded Core介绍文章 | www.embedded.com/design/prototyping-and-development/4218490/Open-Embedded–An-alternative-way-to-build-embedded-Linux-distributions |
| Buildroot和Yocto对比报告 | https://lwn.net/Articles/682540/ |
2. 引入BusyBox
在嵌入式环境中,资源(特别是内存和存储空间)的缺乏是常见问题。Linux系统本身较大,内核通常在2 - 4MB之间,再加上根文件系统、实用程序和配置文件,对资源有限的设备来说是个挑战。BusyBox就是解决这一问题的有力工具。
2.1 BusyBox的概念
BusyBox的理念非常简单,它将众多常用的shell命令集成到一个程序中,避免了每个实用程序单独作为一个程序带来的开销。大多数实用程序需要相同的“辅助”功能,如解析命令行和将ASCII转换为二进制,BusyBox只实现一次这些功能。
2.2 BusyBox的起源与发展
BusyBox项目始于1996年,最初的目标是将完整的Linux系统放在一张软盘上,作为Debian Linux发行版的救援盘或安装盘。后来,嵌入式开发人员发现它可以有效减少Linux在资源受限嵌入式环境中的占用空间,因此该项目得到了广泛发展,如今几乎成为每个商业嵌入式Linux产品的一部分,应用于众多路由器、媒体播放器等设备中。
2.3 BusyBox的特点
BusyBox自称是嵌入式Linux的“瑞士军刀”,技术上被称为“多调用二进制文件”,通过为各种实用程序创建符号链接,这些链接都指向BusyBox可执行文件,从而以多种方式调用程序执行不同命令。
3. 配置和安装BusyBox
3.1 下载BusyBox
可以前往相关网站下载适合自己开发板的BusyBox版本,例如运行在BBB上的版本是1.20.2。
3.2 BusyBox的可配置性
BusyBox具有高度模块化和可配置性,虽然它能够实现300多个shell命令,但不要求系统包含所有命令。配置过程允许你精确选择要包含在系统中的命令。以下是BusyBox近期版本中可用的部分命令列表:
| 命令 | 命令 | 命令 | 命令 |
| — | — | — | — |
| [ | [[ | acpid | addgroup |
| adduser | adjtimex | ar | arp |
| arping | ash | awk | basename |
| beep | blkid | brctl | bunzip2 |
| bzcat | bzip2 | cal | cat |
| catv | chat | chattr | chgrp |
| chmod | chown | chpasswd | chpst |
| chroot | chrt | chvt | cksum |
| clear | cmp | comm | cp |
| cpio | crond | crontab | cryptpw |
| dirname | dmesg | dnsd | dnsdomainname |
| dos2unix | dpkg | du | dumpkmap |
| dumpleases | echo | ed | egrep |
| eject | env | envdir | envuidgid |
| expand | expr | fakeidentd | false |
| fbsplash | fdflush | fdformat | fdisk |
| fgrep | find | findfs | flash_lock |
| flash_unlock | fold | free | freeramdisk |
| fsck | fsck.minix | fsync | ftpd |
| ftpget | ftpput | fuser | getopt |
| hwclock | id | ifconfig | ifdown |
| ifenslave | ifplugd | ifup | inetd |
| init | inotifyd | insmod | install |
| ionice | ip | ipaddr | ipcalc |
| ipcrm | ipcs | iplink | iproute |
| iprule | iptunnel | kbd_mode | kill |
| killall | killall5 | klogd | last |
| length | less | linux32 | linux64 |
| linuxrc | ln | loadfont | loadkmap |
| logger | login | logname | logread |
| md5sum | mdev | mesg | microcom |
| mkdir | mkdosfs | mkfifo | mkfs.minix |
| mkfs.vfat | mknod | mkpasswd | mkswap |
| mktemp | modprobe | more | mount |
| mountpoint | mt | mv | nameif |
| nc | netstat | nice | nmeter |
| nohup | nslookup | od | openvt |
| passwd | patch | pgrep | pidof |
| ping | ping6 | pipe_progress | pivot_root |
| pkill | popmaildir | printenv | printf |
| resize | rm | rmdir | rmmod |
| route | rpm | rpm2cpio | rtcwake |
| run - parts | runlevel | runsv | runsvdir |
| rx | script | scriptreplay | sed |
| sendmail | seq | setarch | setconsole |
| setfont | setkeycodes | setlogcons | setsid |
| setuidgid | sh | sha1sum | sha256sum |
| sha512sum | showkey | slattach | sleep |
| softlimit | sort | split | start - stop - daemon |
| stat | strings | sty | su |
| tac | tail | tar | taskset |
| tcpsvd | tee | telnet | telnetd |
| test | tftp | tftpd | time |
| timeout | top | touch | tr |
| traceroute | true | tty | ttysize |
| udhcpc | udhcpd | udpsvd | umount |
| uname | uncompress | unexpand | uniq |
| unix2dos | unlzma | unlzop | unzip |
| uptime | usleep | uudecode | uuencode |
| vconfig | vi | vlock | volname |
| cut | date | dc | dd |
| deallocvt | delgroup | deluser | depmod |
| devmem | df | dhcprelay | diff |
| getty | grep | gunzip | gzip |
| hd | hdparm | head | hexdump |
| hostid | hostname | httpd | hush |
| losetup | lpd | lpq | lpr |
| ls | lsattr | lsmod | lzmacat |
| lzop | lzopcat | makemime | man |
| ps | pscan | pwd | raidautorun |
| rdate | rdev | readlink | readprofile |
| realpath | reformime | renice | reset |
| sulogin | sum | sv | svlogd |
| swapoff | swapon | switch_root | sync |
| sysctl | syslogd | watch | watchdog |
| wc | wget | which | who |
| whoami | xargs | yes | zcat |
| zcip | | | |
3.3 BusyBox设置
3.3.1 构建选项
在“Build Options”中,你可以选择使用静态链接库或共享库来构建BusyBox。静态链接的BusyBox可执行文件体积更大,但不需要共享库。例如,使用共享库构建的BusyBox为743 kb,而静态链接版本为1.5 MB,不过存放共享库的
/lib
目录总共占用17 MB。这里需要考虑是否需要这些共享库用于其他用途。同时,还可以在此设置交叉编译器前缀,将其设置为
arm - linux -..
。
3.3.2 安装选项
在“Installation Options”中,你可以选择创建符号链接的方式,包括软链接、硬链接或脚本“包装器”。硬链接指向相同数据且共享相同的inode,在inode数量有限的系统中是一个有用的选项;软链接是默认选项,通常也是最佳选择。
3.3.3 安装前缀
“Installation Prefix”是安装BusyBox的文件系统根目录,默认是
./_install
。你可以在此处指定,也可以在执行
make install
步骤时通过添加
CONFIG_PREFIX = /home//,your_home_directory./,your_target_fs..
在命令行中指定。
3.4 小工具(Applets)
BusyBox的300多个小工具分为几个类别,这些类别与BusyBox的目录树密切对应。在很多情况下,BusyBox版本的实用程序会省略一些较晦涩的选项,可以看作是“精简”版本,但可用选项通常足以满足嵌入式系统的需求。在某些情况下,你可以为命令选择所需的选项,例如在“Coreutils”类别中选择
ls
命令时,会发现有几个可选择的
ls
选项,这样做可能是为了在需要时减小代码大小。
3.5 构建和安装
BusyBox使用常规的
make
和
make install
命令来构建和安装软件包。执行
make
后,在BusyBox顶级目录中会出现几个以“busybox”开头的新文件,其中一个是实际的可执行文件
busybox
。接着执行
make install
,它会将
busybox
可执行文件和所有链接复制到配置过程中指定的目标位置,至此BusyBox就可以使用了。
3.6 硬链接与软链接的区别
为了更好地理解硬链接和软链接的区别,我们可以进行以下操作:
在工作站的shell窗口中,进入
B/,your_target_fs./home/samples/src/led
目录,执行以下命令:
ln led.c led2.c
ln -s led.c led3.c
ls -l
stat led.c
stat led2.c
stat led3.c
通过这些命令,我们可以观察到:
led3.c
被识别为指向
led.c
的链接,其长度为指向的文件名的大小(这里是5);而
led2.c
和
led.c
长度相同,引用计数为2,其他文件引用计数为1。
stat
命令可以显示每个文件对应的inode,
led.c
和
led2.c
共享相同的inode,而
led3.c
有不同的inode。
接着执行:
rm led.c
ls -l
在CentOS 7中,
led3.c
的条目会被高亮显示,表示它指向的文件不存在,此时
led2.c
的引用计数变为1。
最后执行:
mv led2.c led.c
ls -l
此时
led3.c
的条目又指向了有效的文件。
这个实验表明,硬链接是同一数据的别名,它们都指向磁盘上的相同数据块,在引用计数变为零之前,数据不能被删除;而软链接或符号链接指向的是文件名,该文件可能存在也可能不存在。
3.7 使用BusyBox
BusyBox可执行文件通常安装在
/bin
目录,该目录存放大多数用户级命令行实用程序。例如,在
/bin
目录中创建以下符号链接:
ln -s busybox ls
现在,当你从shell中调用
ls
时,实际上执行的是BusyBox。程序通过查看
main()
函数的第一个参数(即调用它的名称,这里是
ls
)来确定要执行的操作。对于BusyBox实现的每个命令,都会创建类似的链接。
你也可以直接调用BusyBox,将命令名及其参数作为命令行传递,例如:
busybox ls -l
执行
busybox -help
或仅执行
busybox
本身会显示帮助信息,其中包括当前BusyBox实例中内置的命令列表。
3.8 用户空间初始化
在拥有一个有用的恒温器应用程序后,我们希望该应用程序在系统启动时自动启动,并且在最终产品中可能不需要控制台shell。下面来了解从系统通电到Linux内核启动第一个用户空间进程的初始化过程,该过程主要分为四个步骤:
graph LR
A[电源开启] --> B[阶段1:引导加载程序]
B --> C[阶段2:MLO]
C --> D[U - Boot]
D --> E[Linux内核]
3.8.1 阶段1:引导加载程序
AM335x Sitara具有广泛的内置引导ROM,有多个引导选项。当通电并释放复位引脚时,执行从0x20000的复位异常向量开始,这是一个跳转到TI所称的“Public ROM Code”的指令。该代码会对时钟和看门狗定时器等进行非常底层的初始化,然后根据SYSBOOT引脚的状态构建可引导设备列表。对于每个SYSBOOT引脚值,引导加载程序会构建一个包含四个设备的列表,依次检查每个设备是否有可引导镜像。在BBB的情况下,有两种选项由按钮S2决定:
-
默认情况
:
1. eMMC。如果eMMC中没有可引导镜像,则检查下一个设备。
2. microSD卡。如果没有microSD卡或其中没有可引导镜像,则继续检查。
3. 调试串口。如果该串口没有可引导内容,则继续。
4. USB端口。
-
按下S2时
:
1. SPIO。在BBB上此选项总是失败,所以继续检查下一个设备。
2. microSD卡。如果没有microSD卡或其中没有可引导镜像,则继续。
3. USB端口。
4. 调试串口。如果该串口没有可引导内容,则结束检查。
3.8.2 阶段2:MLO
Sitara SoC包含128 kb的板载RAM,其中109 kb可用于加载引导镜像,这里加载的是第二个阶段的引导加载程序。在BBB上,第二个阶段的加载程序是名为MLO的镜像文件,其任务是设置RAM和各种片外外设的芯片选择,然后加载第三个阶段的加载程序
u - boot
。
3.8.3 U - Boot
u - boot
加载程序继续初始化过程,初始化所需的外设,通常包括串口、网络,可能还有USB。如果自动引导序列未被中断,它通常会将内核从Flash复制到RAM并启动执行。
3.8.4 Linux内核
如果内核是压缩镜像,它会自行解压到RAM中的适当位置,然后初始化所有内核子系统,如内存管理和系统中所有外设的驱动程序。在一定程度上,这可能会重复
u - boot
所做的初始化工作,但内核并不知道
u - boot
做了什么。
4. 用户空间初始化的其他方面
4.1 Systemd
Systemd 是现代 Linux 系统中常用的系统和服务管理器。它负责管理系统的启动、停止、监控和维护服务。与传统的初始化系统相比,Systemd 具有更快的启动速度和更强大的功能。
Systemd 使用单元(Unit)来管理系统资源和服务。单元可以是服务(Service)、挂载点(Mount)、套接字(Socket)等。每个单元都有一个对应的配置文件,通常位于
/etc/systemd/system
或
/usr/lib/systemd/system
目录下。
要管理一个服务,例如启动、停止或重启服务,可以使用以下命令:
# 启动服务
systemctl start service_name
# 停止服务
systemctl stop service_name
# 重启服务
systemctl restart service_name
# 查看服务状态
systemctl status service_name
此外,还可以设置服务在系统启动时自动启动:
systemctl enable service_name
或者禁止服务在系统启动时自动启动:
systemctl disable service_name
4.2 用户空间初始化的“旧方式”
在 Systemd 广泛使用之前,Linux 系统采用了不同的用户空间初始化方式。传统的初始化系统通常基于
/sbin/init
程序,它会读取
/etc/inittab
文件来确定系统的运行级别和要启动的服务。
运行级别是一种定义系统不同操作状态的机制,通常有 0 - 6 共 7 个运行级别:
| 运行级别 | 描述 |
| — | — |
| 0 | 关机 |
| 1 | 单用户模式,用于系统维护 |
| 2 | 多用户模式,无网络支持 |
| 3 | 多用户模式,有网络支持,通常用于服务器 |
| 4 | 未使用,可自定义 |
| 5 | 图形化多用户模式,通常用于桌面系统 |
| 6 | 重启 |
在
/etc/inittab
文件中,可以定义每个运行级别下要执行的操作,例如启动特定的服务或脚本。例如,以下是一个简单的
/etc/inittab
文件示例:
# /etc/inittab
# 默认运行级别
id:3:initdefault:
# 启动 getty 服务,提供终端登录
1:2345:respawn:/sbin/getty 38400 tty1
2:2345:respawn:/sbin/getty 38400 tty2
3:2345:respawn:/sbin/getty 38400 tty3
4:2345:respawn:/sbin/getty 38400 tty4
5:2345:respawn:/sbin/getty 38400 tty5
6:2345:respawn:/sbin/getty 38400 tty6
在这个示例中,系统的默认运行级别是 3,并且在运行级别 2 - 5 下会启动 6 个
getty
服务,分别对应 6 个终端。
5. 总结与展望
通过安装 Yocto 插件,我们可以利用其提供的功能来进行嵌入式 Linux 系统的开发,尽管它具有较高的复杂度,但对于深入学习和开发来说是一个有价值的工具。
BusyBox 的引入为嵌入式系统节省了大量的资源,其高度可配置性使得我们可以根据实际需求选择合适的命令和功能。通过合理配置和安装 BusyBox,我们可以在资源受限的设备上运行一个精简而高效的 Linux 系统。
在用户空间初始化方面,了解不同的初始化方式(如 Systemd 和传统的初始化方式)可以帮助我们根据系统的需求和特点选择合适的方法,确保系统在启动时能够正确地初始化并运行我们所需的应用程序。
未来,随着嵌入式技术的不断发展,我们可以期待更高效、更智能的开发工具和技术出现,进一步提升嵌入式系统的性能和功能。同时,对于资源管理和系统初始化的优化也将成为持续关注的重点,以满足不断增长的应用需求。
在实际开发中,我们可以结合这些知识,根据具体的项目需求选择合适的工具和技术,构建出稳定、高效的嵌入式 Linux 系统。例如,在开发物联网设备时,可以利用 BusyBox 来减小系统的体积,同时使用 Yocto 插件来进行系统的定制和开发;在需要快速启动和高效服务管理的场景下,可以选择使用 Systemd 来进行用户空间的初始化。
总之,嵌入式开发是一个充满挑战和机遇的领域,不断学习和掌握新的知识和技术将有助于我们在这个领域中取得更好的成果。
超级会员免费看
9

被折叠的 条评论
为什么被折叠?



