busybox init
linux启动完成后,运行由Busybox产生的init进程。/sbin/init是系统启动的第一个用户进程,pid=1。
init的工作是根据/etc/inittab脚本来进行系统的初始化工作,关机前的工作等。init代码在BusyBox中init/init.c中,主要进行以下工作:
》为init进程设置信号处理进程。
》对控制台进行初始化。
》解析inittab文件即/etc/inittab。
》若无/etc/inittab,采用默认的inittab,运行初始化脚本/etc/init.d/rcS.
》运行inittab中其他命令。
一、inittab
1.1 格式
# Format:
# <id>:<runlevels>:<action>:<process>
id:不可重复,就是一个命令标号,无特殊含义。
runlevels:控制运行模式,单用户、多用户、图形界面等,此版本未使用。
action:包括sysinit、respawn、wait、once、ctrlaltdel、restart等。
》sysinit:为init提供初始化命令行的路径。
》respawn:在紧跟进程结束后,重启启动该进程(后边的process)。--复位,重启
》askfirst:类似respawn,主要用途是减少系统上执行的终端应用程序的数量,
会在控制台上显示“Please press Enter to active this console"的信息,
并在系统重启之前等待用户按下”Enter“键。
》wait:通知init必须等到相应的进程执行完之后才能继续执行其他的动作。
》once:进程只执行一次,而且不会等待它完成。
》ctrlaltdel:当按下ctrl-Alt-Del组合键时运行的进程。
》shutdown:当系统关机时运行的进程。
》restart:当init进程重启启动时执行的进程,事实上就是init本身。
process:执行的命令。
# /etc/inittab init(8) configuration for BusyBox # # Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org> # # # Note, BusyBox init doesn't support runlevels. The runlevels field is # completely ignored by BusyBox init. If you want runlevels, use sysvinit. # # # Format for each entry: <id>:<runlevels>:<action>:<process> # # <id>: WARNING: This field has a non-traditional meaning for BusyBox init! # # The id field is used by BusyBox init to specify the controlling tty for # the specified process to run on. The contents of this field are # appended to "/dev/" and used as-is. There is no need for this field to # be unique, although if it isn't you may have strange results. If this # field is left blank, then the init's stdin/out will be used. # # <runlevels>: The runlevels field is completely ignored. # # <action>: Valid actions include: sysinit, respawn, askfirst, wait, once, # restart, ctrlaltdel, and shutdown. # # Note: askfirst acts just like respawn, but before running the specified # process it displays the line "Please press Enter to activate this # console." and then waits for the user to press enter before starting # the specified process. # # Note: unrecognized actions (like initdefault) will cause init to emit # an error message, and then go along with its business. # # <process>: Specifies the process to be executed and it's command line. # # Note: BusyBox init works just fine without an inittab. If no inittab is # found, it has the following default behavior: # ::sysinit:/etc/init.d/rcS # ::askfirst:/bin/sh # ::ctrlaltdel:/sbin/reboot # ::shutdown:/sbin/swapoff -a # ::shutdown:/bin/umount -a -r # ::restart:/sbin/init # tty2::askfirst:/bin/sh # tty3::askfirst:/bin/sh # tty4::askfirst:/bin/sh # # Boot-time system configuration/initialization script. # This is run first except when booting in single-user mode. # ::sysinit:/etc/init.d/rcS # /bin/sh invocations on selected ttys # # Note below that we prefix the shell commands with a "-" to indicate to the # shell that it is supposed to be a login shell. Normally this is handled by # login, but since we are bypassing login in this case, BusyBox lets you do # this yourself... # # Start an "askfirst" shell on the console (whatever that may be) ::askfirst:-/bin/sh # Start an "askfirst" shell on /dev/tty2-4 tty2::askfirst:-/bin/sh tty3::askfirst:-/bin/sh tty4::askfirst:-/bin/sh # /sbin/getty invocations for selected ttys tty4::respawn:/sbin/getty 38400 tty5 tty5::respawn:/sbin/getty 38400 tty6 # Example of how to put a getty on a serial line (for a terminal) #::respawn:/sbin/getty -L ttyS0 9600 vt100 #::respawn:/sbin/getty -L ttyS1 9600 vt100 # # Example how to put a getty on a modem line. #::respawn:/sbin/getty 57600 ttyS2 # Stuff to do when restarting the init process ::restart:/sbin/init # Stuff to do before rebooting ::ctrlaltdel:/sbin/reboot ::shutdown:/bin/umount -a -r ::shutdown:/sbin/swapoff -a
不管自己的inittab,还是系统默认inittab,一般首先运行/etc/init.d/rcS脚本,之后再进行后续工作。
bootargs中参数console指定了终端口为ttyS0,所以inittab中console等同于ttyS0,inittab的命令中采用默认终端口执行console或ttyS0。
::sysinit:/etc/init.d/rcS ::respawn:/sbin/getty 115200 tty1 tty2::askfirst:-/bin/sh tty3::askfirst:-/bin/sh ::restart:/sbin/init ::ctrlaltdel:/bin/umount -a -r
这个inittab执行下列动作:
1)将/etc/init.d/rcS设置成系统的初始化文件
2)在115200 bps的虚拟终端tty1上启动一个登陆会话 (注意getty的用法)
3)在虚拟终端tty2和tty3上启动askfirst动作的shell
4)如果init重新启动,将/sbin/init设置成它会执行的程序
5)告诉init,在系统关机的时候执行umount命令卸载所有文件系统,并且在卸载失败时用只读模式冲新安装以保护文件系统。
1.2 inittab执行顺序
跟踪init/init.c中init的执行流程,可知其工作流程:
在init_mian()中完成inittab解析后,组成init_action[],然后顺序阻塞执行(通过run_actions执行命令):
SYSINIT -> WAIT -> ONCE -> 循环RESPAWN|ASKFIRST
阻塞执行SYSINIT|WAIT|ONCE|CTRLALTDEL|SHUTDOWN -> RESPAWN|ASKFIRST仅执行一次
中间接受到信号(CTRLALTDEL)执行信号处理,一般重启设备。
二、rcS
rcS为系统初始化脚本,完成最开始的一些配置工作,可开启应用程序。
#!/bin/sh
mount -a ;mount文件,要mount的文件有fstab指定。 . /etc/profile ;配置环境变量;可不配置,每个终端启动时都会读取.profile和/etc/profile。 echo "configuring network...\n" ;配置网络 ifconfig eth0 down ifconfig eth0 192.168.1.254 ifconfig lo 127.0.0.1 up route add -net 127.0.0.0 netmask 255.0.0.0 lo route add default gw 192.168.1.1 /usr/sbin/telnetd & ;开启telnet echo "------------rcS over.--------------------\n"
最简单的rcS也应该mount fs,开启网口,telnet,ftp可后续根据需要开启。
fstab配置
#<file name> <mount point> <type> <options> <dump> <pass> proc /proc proc defaults 0 0 none /tmp ramfs defaults 0 0 sysfs /sys sysfs defaults 0 0 devpts /dev/pts devpts defaults 0 0
环境变量profile配置
# /etc/profile: system-wide .profile file for the Bourne shells echo echo -n "Processing /etc/profile... " # no-op echo "Done" echo
三、相关命令
3.1 getty
linux的登录主要是由两个文件在控制,/usr/sbin/getty来获得用户名,并进行检查用户名是否存在,然后将用户名传递给/usr/bin/login来获取用户输入密码和检查密码是否正确。
所以要实现linux的自动登录,就要改动这两个文件。
getty实现的主要功能是:
1)打开指定的tty;
2)提示用户登录(login:);
3)获得登录用户名;
4)把用户名传递给login命令 。
login实现的主要功能是:
1)先检查是不是超级用户;
2)提示用户输入密码(通过getpass()实现);
3)检查密码并检查是否quiet登录;
4)设置登录的用户的ID和组ID,并设置相应的环境变量。