前言
内核启动到最后启动的第一个用户进程是init进程,它根据文件系统下的配置文件决定启动哪些程序,init进程是后续所有进程的发起者。
/etc 目录用于存放系统中的配置文件,基本上所有的配置文件都可以在这里找到,这些文件一般都以XXX.conf的形式命名,通过编辑这些文件可以对系统进行更改和管理。进入BusyBox源码目录下,将里面的etc目录复制到根文件系统下:
root@ubuntu:~/rootfs_zht/busybox-1.29.2# cd ./examples/bootfloppy/
root@ubuntu:~/rootfs_zht/busybox-1.29.2/examples/bootfloppy# ls
bootfloppy.txt display.txt etc mkdevs.sh mkrootfs.sh mksyslinux.sh quickstart.txt syslinux.cfg
root@ubuntu:~/rootfs_zht/busybox-1.29.2/examples/bootfloppy# cp etc ~/rootfs_zht/rootfs -rf
etc目录包含了下面几个文件,内容很少,接下来就要去修改它们。
├── fstab
├── init.d
│ └── rcS
├── inittab
└── profile
一、修改初始化文件inittab
inittab格式为:<id>:<runlevels>:<action>:<process>
inittabd的格式在busybox中定义,想要详细了解可以去看busybox源码。运行时busybox会先读取配置文件然后解析,决定要执行的动作。busybox中的进程1是linuxrc,进程1最终最主要的目的是做完其他的事情进入死循环,死循环中反复检查有没有满足条件,当满足action的条件时,执行process这个程序。
<id> :表示这个子进程要使用的控制台,如果省略,则使用与init进程一样的控制台。
<runlevels> :对于BusyBox init程序,这个字段没有意义,可以省略。
<action> :表示init进程如何控制这个子进程。
action名称 | 执行条件 | 说明 |
---|---|---|
sysinit | 系统启动后最先执行 | 只执行一次,init进程等待它结束才继续执行其它动作 |
wait | 系统执行完sysinit进程后 | 只执行一次,init进程等待它结束后才继续执行其它动作 |
once | 系统执行完wait进程后 | 只执行一次,init进程不等待它结束 |
raspawn | 启动完once进程后 | init进程监测发现子进程退出时,重新启动它 |
askfirst | 启动完raspawn进程后 | 与raspawn类似,不过init进程先输出“Please press Enter to activate this console.”,等待用户输入回车键之后才能启动子进程 |
shutdown | 当系统关机时 | 即重启、关闭系统时 |
restart | BusyBox中配置了CONFIG_FEATURE_USE_INITTAB,并且init进程接收到SIGHUP信号时 | 先重新读取、解析/etc/inittab文件、再执行restart程序 |
ctrlaltdel | 按下Ctrl+Alt+Del组合键时 | - |
<process> :要执行的程序,可以是可执行程序,也可以是脚本。如果<process>字段前面有“-”字符,这个程序则称为可以“交互的”。
在/etc/inittab文件的控制下,init进程的行为总结如下。
- 在系统启动前期,init进程首先启动<action>为sysinit、wait、once的3类子进程。
- 在系统正常运行期间,init进程首先启动<action>为raspawn、askfirst的2类子进程并监视它们,发现某个子进程退出时,重新启动它们。
- 在系统退出时,执行<action>为shutdown、restart、ctrlaltdel的3类子进程。
inittab修改为以下内容:
#first:run the system script file
::sysinit:/etc/init.d/rcS
::askfirst:-/bin/sh
::ctrlaltdel:-/sbin/reboot
#umount all filesystem
::shutdown:/bin/umount -a -r
#restart init process
::restart:/sbin/init
系统启动后首先执行一次/etc/init.d/rcS
脚本,脚本执行结束后执行profile
脚本(/bin/sh加上”-”的话就会在登陆终端之后调用/etc/目录下的profile文件,而不加”-”则不会执行这个脚本),再执行/bin/sh
程序,之后就可以在控制台输入交互命令,进程进入死循环,始终检查是否满足raspawn或者askfirst条件,一旦满足就执行相应子进程;系统退出时执行shutdown、restart、ctrlaltdel的子进程。
运行结果如下:
二、修改/etc/init.d/rcS文件
#! /bin/sh
umask 022
mount -a
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
ifconfig eth0 192.168.1.10
/bin/hostname -F /etc/hostname
第1行:表示这是一个脚本文件,指明了脚本解释器的路径,使用sh进行解析。
第2行:设置linux系统的umask的值,决定用户创建文件的默认权限。
第3行:mount -a
用来挂载所有/etc/fstab
指定的文件系统。
第4、5行:利用BusyBox自带的mdev可执行文件在系统启动时创建所有的设备节点。mdev的作用主要有两个:初始化/dev目录和动态更新,动态更新不仅是更新/dev目录,还支持热插拔动作(前提是保证内核中支持hotplug)。
第6行:设置板子IP地址。
第7行:-F来指定一个主机名的配置文件,文件名一般叫hostname或者HOSTNAME。
三、修改fstab文件
详细参考:https://blog.csdn.net/richerg85/article/details/17917129
# /etc/fstab: static file system information.
#
# Use 'vol_id --uuid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
proc /proc proc defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /var tmpfs defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
- file system:要挂载的分区或存储设备。
- mount point:要挂载的目录。
- type:要挂载设备或是分区的文件系统类型,支持许多种不同的文件系统:ext2, ext3, ext4, reiserfs, xfs, jfs, smbfs, iso9660, vfat, ntfs, swap 及 auto。 设置成auto类型,表示自动检测文件系统类型。
- options:权限选项, 默认为defaults(rw, suid, dev, exec, auto, nouser, async)。
- dump:自检设置,1:开机后磁盘自检 0:不自检
- pass:优先级设置,若自检为1则可对多块硬盘进行优先级设置。
四、创建文件夹
fstab文件中指定的挂载点现在在rootfs中并不存在,所以需要在rootfs目录下
手动创建这几个文件夹。如果不创建的话,系统启动会提示挂载失败。
proc虚拟文件系统
:早期内核版本很难调试,为了降低调试难度,开发者尝试加入proc文件系统,属性为只读
。
sys虚拟文件系统
:本质和proc一样,都是用于调试内核。不同的是:proc缺乏管理规范,东西又乱又杂;而新加入的sys,制定了一系列管理策略和规范,sys还增加了可写属性
。
mkdir proc sys var tmp dev
这个时候重新运行rootfs就可以看到proc下面多出了很多文件,说明挂载成功了。
五、修改profile文件
Linux是一个多用户的操作系统,每个用户登录系统后都会有一个专用的运行环境,这个运行环境就是一组环境变量的定义,将定义集中在一个文件中,即是/etc/profile文件,可以通过修改profile文件对运行环境进行配置。
export PATH=/bin:/sbin:/usr/bin:/usr/sbin
export LD_LIBRARY_PATH=lib:/usr/lib
HOSTNAME='/bin/hostname'
export PS1="\e[32;01m\u@\h\e[00m:\e[34;01m\w\e[00m\# "
alias ll='/bin/ls -laF'
第1行:定义PATH变量,赋值为后面的字符串,然后导出为环境变量。PATH表示了当前用户的系统命令、常用命令及应用程序的默认存储路径。运行指令时,shell会按照列出的路径顺序依次查找符合要求的可执行文件。
第2行:LD_LIBRARY_PATH设置了应用程序库的路径。
第3行:定义变量并赋值
第4行:定义PS1变量并导出为环境变量,PS1是基本提示符,以上格式与ubuntu同款。
- \e[32;01m:让后面的
\u@\h
显示为绿色,高亮显示 - \u:显示当前用户名称
- \h:显示主机名称
- \e[00m:关闭所有属性(用于显示冒号)
- \e[34;01m:让后面的
\w
显示为蓝色,高亮显示 - \w:显示完整的工作目录名称,\W显示当前目录
- \# :root用户提示符为# ,普通用户为$。
- 注意字符串最后面要有个空格!
第5行: alias用来设置别名,简化常用的较长命令
PS1设置字符序列颜色格式为: \e[ F;B;Cm
①.F为前景色,B为背景色,C为代码;②.这个地方只填一个值就不需要写分号,填了多个值才需要用分号隔开;③.FBC不分先后次序,根据值来设定相应颜色。
颜色表
前景 | 背景 | 颜色 |
---|---|---|
30 | 40 | 黑色 |
31 | 41 | 红色 |
32 | 42 | 绿色 |
33 | 43 | 黄色 |
34 | 44 | 蓝色 |
35 | 45 | 紫红色 |
36 | 46 | 青蓝色 |
37 | 47 | 白色 |
代码表
代码 | 意义 |
---|---|
0 | 关闭所有属性 |
1 | 高亮显示 |
4 | 下划线 |
5 | 闪烁 |
7 | 反白显示 |
8 | 不可见 |
root@ubuntu:~/rootfs_zht/rootfs/etc# vi hostname
# 然后输入自定义主机名
输入的主机名在命令提示符中显示,用户名暂时不会显示,因为还没有做用户登录。
参考资料:
- <<嵌入式Linux软硬件开发详解>>
- 朱老师嵌入式Linux网课
- https://blog.csdn.net/qq_34208467/article/details/81019467