Linux搭建根文件系统
根文件系统首先是内核启动时所 mount(挂载)的第一个文件系统,内核代码映像文件保存在根文件系统中,而系统引导启动程序会在根文件系统挂载之后从中把一些基本的初始化脚本和服务等加载到内存中去运行。
使用BusyBox构建根文件系统
先在NFS服务器目录下创建一个rootfs文件夹,用于通过NFS挂载根文件系统。(存放在NFS下的文件夹)
获取的busybox压缩包
放入任意文件夹中并解压。(存放在自定义任意文件夹)
/*命令*/
mkdir rootfs
tar -vxjf busybox-1.29.0.tar.bz2
完成后如下:
接下来打开顶层Makefile,添加 ARCH 和 CROSS_COMPILE(绝对路径) 的值。
让busybox支持中文
首先打开busybox-1.29.0/libbb目录下的 printable_string.c 文件,找到 printable_string 函数。
在vim编辑器中,在命令行模式下:用以下命令可以搜索字符串。
/xxx
修改后的代码如下
const char* FAST_FUNC printable_string(uni_stat_t *stats, const char *str)
{
char *dst;
const char *s;
s = str;
while (1) {
unsigned char c = *s;
if (c == '\0') {
/* 99+% of inputs do not need conversion */
if (stats) {
stats->byte_count = (s - str);
stats->unicode_count = (s - str);
stats->unicode_width = (s - str);
}
return str;
}
if (c < ' ')
break;
/* if (c >= 0x7f)
break; */
s++;
}
#if ENABLE_UNICODE_SUPPORT
dst = unicode_conv_to_printable(stats, str);
#else
{
char *d = dst = xstrdup(str);
while (1) {
unsigned char c = *d;
if (c == '\0')
/* if (c < ' ' || c >= 0x7f)*/
if(c < ' ')
*d = '?';
d++;
}
if (stats) {
stats->byte_count = (d - dst);
stats->unicode_count = (d - dst);
stats->unicode_width = (d - dst);
}
}
#endif
return auto_string(dst);
}
再打开 unicode.c 文件,找到 unicode_conv_to_printable2 函数,修改后如下
static char* FAST_FUNC unicode_conv_to_printable2(uni_stat_t *stats, const char *src, unsigned width, int flags)
{
char *dst;
unsigned dst_len;
unsigned uni_count;
unsigned uni_width;
if (unicode_status != UNICODE_ON) {
char *d;
if (flags & UNI_FLAG_PAD) {
d = dst = xmalloc(width + 1);
while ((int)--width >= 0) {
unsigned char c = *src;
if (c == '\0') {
do
*d++ = ' ';
while ((int)--width >= 0);
break;
}
/* *d++ = (c >= ' ' && c < 0x7f) ? c : '?'; */
*d++ = (c >= ' ') ? c : '?';
src++;
}
*d = '\0';
} else {
d = dst = xstrndup(src, width);
while (*d) {
unsigned char c = *d;
/* if (c < ' ' || c >= 0x7f) */
if(c < ' ')
*d = '?';
d++;
}
}
if (stats) {
stats->byte_count = (d - dst);
stats->unicode_count = (d - dst);
stats->unicode_width = (d - dst);
}
return dst;
}
......
}
配置busybox
默认配置命令:
make defconfig
利用图形化配置界面进行配置,命令:
make menuconfig
打开后如下图所示:
要配置的路径:
1.
Location:
-> Settings
-> Build static binary (no shared libs) //不选中
2.
Location:
-> Settings
-> vi-style line editing commands //选中
3.
Location:
-> Linux Module Utilities
-> Simplified modutils //不选中
4.
Location:
-> Linux System Utilities
-> mdev (16 kb)//确保下面的全部选中,默认都是选中的
5.
Location:
-> Settings
-> Support Unicode //选中
-> Check $LC_ALL, $LC_CTYPE and $LANG environment variables //选中
编译busybox
make
make install CONFIG_PREFIX=/home/swiler/workdir/rootfs
编译完成后如下所示:
向根文件系统添加lib库
此时的rootfs目录下的内容如图所示:
接下来在根目录下新建 lib 目录,添加动态库,动态库位于交叉编译器中
目录
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
拷贝所有的带so和.a的文件到lib目录下
cp *so* *.a /home/swiler/workdir/rootfs/lib/ -d
注意要将 ld-linux-armhf.so.3 这个换成文件本身,不能是一个软链接文件。删除原来的软链接文件,再复制一份其本身即可。
/* 命令 */
rm ld-linux-armhf.so.3
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib
cp ld-linux-armhf.so.3 /home/swiler/workdir/rootfs/lib/
再进入另一个目录下,拷贝其它的库文件
目录
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
/* 命令 */
cd /usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/lib
cp *so* *.a /home/swiler/workdir/rootfs/lib/ -d
拷贝完成后lib目录内容如下图所示
接着在usr目录下新建lib目录添加库文件
再进入到如下目录拷贝库文件到usr/lib目录下
目录:
/usr/local/arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/arm-linux-gnueabihf/libc/usr/lib
/* 命令 */
cp *so* *.a /home/swiler/workdir/rootfs/usr/lib/ -d
拷贝完成后 usr/lib 目录内容如下图所示
创建其它文件夹
创建完如下图所示
测试
进入uboot模式,配置bootargs变量
格式如下:
root=/dev/nfs nfsroot=[<server-ip>:]<root-dir>[,<nfs-options>] ip=<client-ip>:<server-ip>:<gw-ip>:<netmask>:<hostname>:<device>:<autoconf>:<dns0-ip>:<dns1-ip>
(说明)
server-ip | 服务器 IP 地址 |
---|---|
root-dir | 根文件系统的存放路径 |
nfs-options | NFS 的其他可选选项,一般不设置 |
client-ip | 客户端 IP 地址 |
server-ip | 服务器 IP 地址 |
gw-ip | 网关地址 |
netmask | 子网掩码 |
hostname | 客户机的名字,一般不设置,此值可以空着 |
device | 设备名,也就是网卡名,一般是 eth0,eth1 |
autoconf | 自动配置,一般不使用,所以设置为 off |
dns0-ip | DNS0 服务器 IP 地址,不使用 |
dns1-ip | DNS1 服务器 IP 地址,不使用 |
完整命令例子:
命令
setenv bootargs 'console=ttymxc0,115200 root=/dev/nfs nfsroot=192.168.1.250:
/home/swiler/workdir/rootfs,proto=tcp rw ip=192.168.1.251:192.168.1.250:192.168.1.1:
255.255.255.0::eth0:off' //设置 bootargs
saveenv //保存环境变量
启动Linux内核
boot命令启动内核,进入后可以用 ls 命令看看根文件系统是否工作
下图就是正常启动后的样子
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0zF8xie8-1651580862231)(C:\Users\15894\AppData\Roaming\Typora\typora-user-images\image-20220503195502573.png)]
进一步完善根文件系统
rcS脚本
在 /etc/init.d 目录创建rcS脚本,帮助Linux内核启动后需要启动的一些服务。
内容如下:
#!/bin/sh
PATH=/sbin:/bin:/usr/sbin:/usr/bin:$PATH
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/lib:/usr/lib
export PATH LD_LIBRARY_PATH
mount -a
mkdir /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
给予文件可执行权限
chmod 777 rcS
之后要修改该文件时,如果碰到 Read-only file system 的错误时,可以利用以下命令修改目录为可读写模式
/data 指的是 data 目录
mount -o remount -rw /data
fstab文件
在 /etc 目录下创建 fstab 文件
内容如下:
#<file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
file system | 要挂载的特殊的设备 |
---|---|
mount point | 挂载点 |
type | 文件系统类型 |
options | 挂载选项,“man mount”命令可以查看具体的选项 |
dump | 为 1 的话表示允许备份,为 0 不备份 |
pass | 磁盘检查设置,为 0 表示不检查。只有根目录设置为1 |
inittab文件
在 /etc 目录下创建 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
动作 | 描述 |
---|---|
sysinit | 在系统初始化的时候 process 才会执行一次 |
respawn | 当 process 终止以后马上启动一个新的 |
askfirst | 和 respawn 类似,在运行 process 之前在控制台上显示“Please press Enter to activate this console.”。只要用户按下“Enter”键以后才会执行 process |
wait | 告诉 init,要等待相应的进程执行完以后才能继续执行 |
once | 仅执行一次,而且不会等待 process 执行完成 |
restart | 当 init 重启的时候才会执行 procee |
ctrlaltdel | 当按下 ctrl+alt+del 组合键才会执行 process |
shutdown | 关机的时候执行 process |
resolv.conf文件
该文件是用来配置域名解析服务器的 IP 地址,一般域名解析地址可以设置为所处网络的网关地址,比如 192.168.1.1。也可以设置为 114.114.114.114,这个是运营商的域名解析服务器地址。配置完,重启后就可以联网了。
文件创建在 /etc 目录下,内容如下:
nameserver 114.114.114.114
nameserver 192.168.1.1
ping成功则如下图所示:
这样根文件系统也就配置好了。