手把手教你构建嵌入式Linux根文件系统

/bin:此目录下存放着系统需要的可执行文件,一般都是一些命令,比如 ls、mv 等命令
/dev:device的缩写,此目录下的文件都是和设备有关的。在Linux下一切皆文件,即使是硬件设备,也是以文件的形式存在的,比如/dev/ttymxc0就表示串口0
/etc:此目录下存放着各种配置文件
/lib:library的简称,也就是库,此目录下存放着Linux所必须的库文件
/mnt:临时挂载目录,一般是空目录,可在此目录下创建空的子目录,比如/mnt/sd、/mnt/usb,这样就可以将SD卡或者U盘挂载到/mnt/sd 或者/mnt/usb 目录中
/proc:此目录一般是空的,当Linux系统启动以后会将此目录作为proc文件系统的挂载点,proc是个虚拟文件系统,没有实际的存储设备。proc里面的文件都是临时存在的,一般用来存储系统运行信息文件
/usr:不是user的缩写,而是Unix Software Resource的缩写,即Unix操作系统软件资源目录。此目录下也存放着很多软件,一般系统安装完成以后此目录占用的空间最多
/var:此目录存放一些可以改变的数据
/sbin:此目录下存放一些可执行文件,但此目录下的文件或命令只有管理员才能使用,主要用于系统管理
/sys:系统启动以后此目录作为 sysfs文件系统的挂载点,sysfs是一个类似于 proc文件系统的特殊文件系统,sysfs也是基于RAM的文件系统,也就是说它也没有实际的存储设备。此目录是系统设备管理的重要目录
/opt:可选的文件、软件存放区,由用户选择将哪些文件或软件放到此目录中

1.busybox

首先获取busybox源码
https://www.busybox.net/downloads/
我这边使用的是1.33.1的源码
解压源码进入顶层目录 make menuconfig
image.png

1.1 配置交叉编译工具链

Settings -> Cross compiler prefix
image.png

1.2 不要选择静态编译

Settings -> Build static binary (no shared libs)
用于选择是静态编译还是动态编译,静态编译不需要库文件,编译出来的库很大;动态编译要求根文件系统中有库文件,编译出来的 busybox 小很多。这里不使用静态编译,保持默认不选
image.png

1.3 添加vi command支持

Settings -> vi-style line editing commands
image.png

1.4 添加硬件热拔插支持

Linux System Utilities -> mdev
image.png

1.5 为busybox添加中文支持

image.png
修改libbb/printable_string.c
在printable_string2函数中
image.png
修改libbb/unicode.c
在unicode_conv_to_printable2函数中
image.png
打开make menuconfig勾选Support Unicode
和Check $LC_ALL, $LC_CTYPE and $LANG environment variables
Settings -> Support Unicode
image.png

1.6 编译busybox

在busybox源码顶层目录下运行make
image.png
编译完成后通过make install CONFIG_PREFIX=
来安装到指定路径
image.png
image.png
成功安装啦,注意linuxrc文件是用来挂载根文件的千万不要删掉

1.7 完善busybox根文件系统

1.7.1 完善目录

通过编译 busybox 生成了 bin、 sbin 和 usr 这三个目录, 以及 linuxrc 这个文件。 busybox 的工作就完成了, 还需要一些其他的文件完善文件系统
使用 mkdir 分别建立 dev,etc,lib,mnt,proc,sys,tmp,var目录

mkdir dev etc lib mnt proc sys tmp var

image.png

1.7.2 创建eth0-setting文件

在/etc目录下建立“ eth0-setting” 文件, 并在“ eth0-setting” 文件里输入下面的内容

IP=192.168.1.230
Mask=255.255.255.0
Gateway=192.168.1.1
DNS=192.168.1.1
MAC=08:90:90:90:90:90

并chmod 755 eth0-setting

1.7.3 创建init.d目录并创建ifconfig-eth0

在/etc目录下建立init.d目录并创建ifconfig-eth0文件
在ifconfig-eth0里面添加下面内容

#!/bin/sh

echo -n Try to bring eth0 interface up......>/dev/ttymxc0
# echo的节点要根据芯片来设置
if [ -f /etc/eth0-setting ] ; then
      source /etc/eth0-setting
         if grep -q "^/dev/root / nfs " /etc/mtab ; then
                 echo -n NFS root ... > /dev/ttymxc0
         else
                 ifconfig eth0 down
                 ifconfig eth0 hw ether $MAC
                 ifconfig eth0 $IP netmask $Mask up
                 route add default gw $Gateway
         fi
         echo nameserver $DNS > /etc/resolv.conf

else
         if grep -q "^/dev/root / nfs " /etc/mtab ; then
                 echo -n NFS root ... > /dev/ttymxc0
         else
                 /sbin/ifconfig eth0 192.168.253.12 netmask 255.255.255.0 up
         fi
fi
 echo Done > /dev/ttymxc0

并chmod 755 ifconfig-eth0

1.7.4 创建rcS文件

在init.d文件夹下创建rcS文件,他是开机启动脚本
在rcS文件中输入以下内容

#! /bin/sh
#初始化环境变量PATH,操作系统执行程序默认到PATH指定的目录下寻找该程序
PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/bin:
runlevel=S
prevlevel=N
umask 022

export PATH runlevel prevlevel
# 
#       Trap CTRL-C &c only in this shell so we can interrupt subprocesses.
#
trap ":" INT QUIT TSTP
/bin/hostname iTOP-iMX6UL
#/bin/mount -n -t proc none /proc
#/bin/mount -n -t sysfs none /sys
#/bin/mount -n -t usbfs none /proc/bus/usb
#/bin/mount -t ramfs none /dev
[ -e /proc/1 ] || /bin/mount -n -t proc none /proc
[ -e /sys/class ] || /bin/mount -n -t sysfs none /sys
[ -e /dev/tty ] || /bin/mount -t ramfs none /dev

echo /sbin/mdev > /proc/sys/kernel/hotplug
/sbin/mdev -s
#/bin/hotplug
# mounting file system specified in /etc/fstab
mkdir -p /dev/pts
mkdir -p /dev/shm
/bin/mount -n -t devpts none /dev/pts -o mode=0622
/bin/mount -n -t tmpfs tmpfs /dev/shm
#/bin/mount -n -t ramfs none /tmp
#/bin/mount -n -t ramfs none /var
mkdir -p /var/empty
mkdir -p /var/log
mkdir -p /var/log/boa
mkdir -p /var/lock
mkdir -p /var/run
mkdir -p /var/tmp
#ln -sf /dev/ttyS2 /dev/tty2
#ln -sf /dev/ttyS2 /dev/tty3
#ln -sf /dev/ttyS2 /dev/tty4
syslogd
/etc/rc.d/init.d/netd start
echo " " > /dev/tty1
echo "Starting networking..." > /dev/tty1
#sleep 1
#/etc/rc.d/init.d/httpd start
#echo " " > /dev/tty1
#echo "Starting web server..." > /dev/tty1
#sleep 1
#/etc/rc.d/init.d/leds start
#echo " " > /dev/tty1
#echo "Starting leds service..." > /dev/tty1
#echo " "
#sleep 1
#echo "*************************************" > /dev/ttySAC2
#echo " http://www.topeet.com.cn " > /dev/ttySAC2
#echo "*************************************" > /dev/ttySAC2
#echo "*************************************"
#echo " http://www.topeet.com.cn "
#echo "*************************************"
mkdir /mnt/disk
sleep 1
/sbin/ifconfig lo 127.0.0.1
/etc/init.d/ifconfig-eth0

并chmod 755 rcS

1.7.5 创建passwd文件

返回到“init.d” 文件夹的上一级目录etc,创建passwd文件,在passwd里面添加

root::0:0:root:/:/bin/sh
bin:*:1:1:bin:/bin:
daemon:*:2:2:daemon:/sbin:
nobody:*:99:99:Nobody:/:

并chmod 755 passwd
passwd 文件是用来保存用户的信息的,是一个纯文本文件。格式如下:

name:password:uid:gid:comment:home:shell
image.png

1.7.6 创建profile文件

在/etc目录下创建profile文件并输入下面内容

# Ash profile
# vim: syntax=sh

# No core files by default
ulimit -S -c 0 > /dev/null 2>&1 
#发生段错误的时候不产生core文件
#并且输出的错误信息不显示在显示器上

USER="`id -un`" #获得user
LOGNAME=$USER
PS1='[$USER@$HOSTNAME]# '
PATH=$PATH

HOSTNAME=`/bin/hostname`

export USER LOGNAME PS1 PATH

并chmod 755 profile

1.7.7 创建netd文件

在/etc 目录下创建rc.d文件夹, 在rc.d文件夹下创建init.d文件夹, 在init.d文件夹中创建netd文件

mkdir -p rc.d/inid.d
cd rc.d/init.d
touch netd

在netd文件中添加下面内容

#!/bin/sh

base=inetd

# See how we were called.

case "$1" in
  	start)
      		/usr/sbin/$base
  	;;
  	stop)
     		pid=`/bin/pidof $base`
     		if [ -n "$pid" ]; then
       			kill -9 $pid
     		fi
   	;;
esac

exit 0

并chmod 755 netd

1.7.8 创建inittab文件

在/etc目录下创建inittab文件并输入以下内容

::sysinit:/etc/init.d/rcS
console::askfirst:-/bin/sh
::restart:/sbin/init
::ctrlaltdel:/sbin/reboot
::shutdown:/bin/umount -a -r
::shutdown:/sbin/swapoff -a

1.7.9 将交叉编译工具中的 lib 库复制到 lib 下

cp -d /opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/cortexa7hf-neon-poky-linux-gnueabi/lib/*so* ./lib

库文件 ld-linux-armhf.so.3 在根文件系统中不能作为符号链接文件, 需要修改为普通库文件。 否则在根文件系统中可执行程序不能执行。 先将ld-linux-armhf.so.3 删掉, 重新拷贝一份到 rootfs/lib 目录下。 执行下列命令

rm lib/ld-linux-armhf.so.3 
cp /opt/fsl-imx-x11/4.1.15-2.0.0/sysroots/cortexa7hf-n eon-poky-linux-gnueabi/lib/ld-linux-armhf.so.3 ./lib/ 

1.7.10 在etc目录下创建fstab文件并输入下文内容

proc /proc proc         defaults 0 0
tmpfs /tmp tmpfs        defaults 0 0
sysfs /sys sysfs        defaults 0 0

1.8 打包根文件系统

image.png
经过前面的步骤我们已经制作完成了一个最小 linux 文件系统, 然后我们在文件系统目录下( /home/topeet/work/busybox/busybox-1.29.0/rootfs) 执行“ sudo tar jcvf rootfs.tar.bz2 bin dev etc lib linuxrc mnt proc root sbin sys tmp usr” 压缩命令, 生成 rootfs.tar.bz2 文件系统镜像

2. buildroot

我这边使用的是buildroot-2023.02.9
安装依赖包

sudo apt-get install zlib1g-dev unzip gcc g++ aptitude lib32stdc++6-4.8-dbg make build-essential libncurses5 libncurses5-dev u-boot-tools traceroute -y

2.1 Target options设置

设置目标芯片的架构
Target options
image.png
按照imx6ull的信息进行填写即可

2.2 Toolchain

image.png

2.3 Build options设置

主要关注这三个选项
image.png
知道是干啥的就行,不用改他

2.4 System configuration设置

image.png

2.5 设置输出格式

Filesystem images -> Compression methon
image.png
对于imx6芯片他的根文件系统使用bz2格式

然后就可以make了
image.png
由于ELFBOARD使用的内核版本是4.1.15,要在buildroot中配置一致
首先将4.1.15转成hex 04010F, 然后再把hex转成十进制
image.png
是262415
进入交叉编译器目录 libc/usr/include/linux/version.h里面
image.png

3.buildroot好用的包

3.1 dropbear -- 轻量级的SSH

3.2 gesftpserver -- 嵌入式系统的SFTP(安全文件传输协议)服务器实现

在filezila中可以通过sftp协议跟开发板进行文件传输

3.3 Qt5 -- Qt5 GUI库

image.png
选中Qt5之后进入Qt5设置
首先说几个必须的选项
gui module -> widgets module
gui module -> Default graphical platform 输入 linuxfb
fontconfig support
GIF support
JPEG support
image.png
还有触摸支持
image.png

posted @ 2024-04-07 13:00  flose  阅读(1322)  评论(0)    收藏  举报