Difference between revisions of "EMAC OE Boot Process Customization"
(removed custom / overriding init section) |
|||
(47 intermediate revisions by 7 users not shown) | |||
Line 1: | Line 1: | ||
+ | {{todo|SEOKWREV (10.31.13-11:02->MW+)(10.31.13-20:35->MD+)(11.06.13-12:17->JG+)(03.06.14-14:50->BS-);(04.10.14-16:05->BS+)|Michael Welling|project=oe 4,oe 5,mw,md,bs,SEOKWREV}} | ||
+ | |||
+ | {{#seo: | ||
+ | |title=EMAC OE Boot Process Customization | ||
+ | |titlemode=append | ||
+ | |keywords=Boot Process,Busybox,System V | ||
+ | |description=This guide describes the initialization method used for EMAC OE systems and provides information on customizing the boot process. | ||
+ | }} | ||
When designing an embedded system, it is often necessary to add or remove applications and tasks from the system initialization sequence. This guide describes the initialization method used for EMAC OE systems and provides information on customizing the boot process. | When designing an embedded system, it is often necessary to add or remove applications and tasks from the system initialization sequence. This guide describes the initialization method used for EMAC OE systems and provides information on customizing the boot process. | ||
== System V Initialization == | == System V Initialization == | ||
− | EMAC OE uses the System V Initialization method. This is a simple method for system initialization using a set of scripts run in sequential order. When the kernel has finished loading, <code>/sbin/init</code> is started to initialize the userspace services | + | EMAC OE uses the System V Initialization method. This is a simple method for system initialization using a set of scripts run in sequential order. When the kernel has finished loading, <code>/sbin/init</code> is started to initialize the userspace services in the system. |
=== Runlevels === | === Runlevels === | ||
− | System V Init uses different runlevels to control the boot process. Each runlevel | + | System V Init uses different runlevels to control the boot process. Each runlevel is associated with a set of scripts that are run sequentially to start various services on the system. The default runlevel on EMAC OE systems is 5. This is set in <code>/etc/inittab</code> with the line: |
+ | <syntaxhighlight lang="text"> | ||
# The default runlevel. | # The default runlevel. | ||
id:5:initdefault: | id:5:initdefault: | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | There are a total of seven runlevels available in System V Init, labeled 0 through 6. Runlevel 5 is the full user level in EMAC OE systems, regardless of whether a GUI is installed on the board or not. Runlevel 0 halts the system, and runlevel 6 is used for reboot. The other runlevels can be used for other purposes if desired configuring different levels of user functionality in each runlevel. | ||
− | + | During boot, the scripts <code>/etc/init.d/rcS</code> and <code>/etc/init.d/rc</code> are executed to launch the scripts in <code>/etc/rcS.d/</code> followed by the scripts in <code>/etc/rc5.d/</code> (assuming that 5 is the default runlevel). The <code>/etc/rcS.d/</code> and <code>/etc/rc5.d/</code> directories contain a set of symbolic links starting with 'S'. These links are used to run scripts stored in <code>/etc/init.d/</code> in a prescribed order. All of these startup scripts are passed the argument <code>start</code>. During halt or reboot, the scripts in <code>/etc/rc0.d/</code> or <code>/etc/rc6.d/</code> starting with a 'K' are run in lexicographic order with the argument <code>stop</code>. | |
− | + | To control the order in which the scripts are run, each symbolic link contains a number 00-99 immediately after the 'S' or 'K'. Symbolic links with the same numeric prefix will be run in alphanumeric order. For example, the listing below illustrates the files in <code>/etc/rcS.d/</code> that will be run in order before entering the default runlevel: | |
− | + | <syntaxhighlight lang="text"> | |
− | + | root@emac-oe:/etc/rcS.d# ls | |
− | + | S02banner S20modutils.sh S40networking | |
− | + | S03sysfs S30ramdisk S41ifplugd | |
− | + | S03udev S35mountall.sh S45mountnfs.sh | |
− | + | S05devices S37populate-volatile.sh S55bootmisc.sh | |
− | + | S06alignment S38devpts.sh S98ipkg-configure | |
+ | S10checkroot S39hostname.sh S99finish.sh | ||
+ | </syntaxhighlight> | ||
The action to perform at each level is specified in <code>/etc/inittab</code>. For example, the following lines are used to trigger the execution of the <code>/etc/init.d/rcS</code> and <code>/etc/init.d/rc</code> scripts: | The action to perform at each level is specified in <code>/etc/inittab</code>. For example, the following lines are used to trigger the execution of the <code>/etc/init.d/rcS</code> and <code>/etc/init.d/rc</code> scripts: | ||
+ | <syntaxhighlight lang="text"> | ||
si::sysinit:/etc/init.d/rcS | si::sysinit:/etc/init.d/rcS | ||
.... | .... | ||
l5:5:wait:/etc/init.d/rc 5 | l5:5:wait:/etc/init.d/rc 5 | ||
.... | .... | ||
+ | </syntaxhighlight> | ||
=== Initscripts === | === Initscripts === | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | The directory <code>/etc/init.d/</code> holds all of the initialization scripts that are run by init during boot or shutdown. These scripts should be designed to accept at least three arguments: <code>start</code>, <code>stop</code>, or <code>restart</code>. As described in the previous section, <code>/etc/rc*.d/</code> directories contain symbolic links to the scripts in <code>/etc/init.d/</code>. This structure allows for easy modification of the boot process and the ability for a script to be run at different places in different runlevels. The detailed listing of the <code>/etc/rcS.d/</code> directory is shown below: | |
+ | |||
+ | <syntaxhighlight lang="text"> | ||
+ | root@emac-oe:/etc/rcS.d# ls -l | ||
+ | lrwxrwxrwx 1 root root 16 Dec 31 1969 S02banner -> ../init.d/banner | ||
+ | lrwxrwxrwx 1 root root 18 Dec 31 1969 S03sysfs -> ../init.d/sysfs.sh | ||
+ | lrwxrwxrwx 1 root root 14 Dec 31 1969 S03udev -> ../init.d/udev | ||
+ | lrwxrwxrwx 1 root root 17 Dec 31 1969 S05devices -> ../init.d/devices | ||
+ | lrwxrwxrwx 1 root root 22 Dec 31 1969 S06alignment -> ../init.d/alignment.sh | ||
+ | lrwxrwxrwx 1 root root 19 Dec 31 1969 S10checkroot -> ../init.d/checkroot | ||
+ | lrwxrwxrwx 1 root root 21 Dec 31 1969 S20modutils.sh -> ../init.d/modutils.sh | ||
+ | lrwxrwxrwx 1 root root 17 Dec 31 1969 S30ramdisk -> ../init.d/ramdisk | ||
+ | lrwxrwxrwx 1 root root 21 Dec 31 1969 S35mountall.sh -> ../init.d/mountall.sh | ||
+ | lrwxrwxrwx 1 root root 30 Dec 31 1969 S37populate-volatile.sh -> ../init.d/populate-volatile.sh | ||
+ | lrwxrwxrwx 1 root root 19 Dec 31 1969 S38devpts.sh -> ../init.d/devpts.sh | ||
+ | lrwxrwxrwx 1 root root 21 Dec 31 1969 S39hostname.sh -> ../init.d/hostname.sh | ||
+ | lrwxrwxrwx 1 root root 20 Dec 31 1969 S40networking -> ../init.d/networking | ||
+ | lrwxrwxrwx 1 root root 17 Dec 31 1969 S41ifplugd -> ../init.d/ifplugd | ||
+ | lrwxrwxrwx 1 root root 21 Dec 31 1969 S45mountnfs.sh -> ../init.d/mountnfs.sh | ||
+ | lrwxrwxrwx 1 root root 21 Dec 31 1969 S55bootmisc.sh -> ../init.d/bootmisc.sh | ||
+ | lrwxrwxrwx 1 root root 24 Dec 31 1969 S98ipkg-configure -> ../init.d/ipkg-configure | ||
+ | lrwxrwxrwx 1 root root 19 Dec 31 1969 S99finish.sh -> ../init.d/finish.sh | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | The other boot scripts on the system can be used as examples when creating custom initscripts. The application that is being started should be stored in the system <code>PATH</code>, such as <code>/usr/bin/</code>, and started from the script. For example, the <code>busybox-httpd</code> initscript is shown below. | ||
<syntaxhighlight lang=bash> | <syntaxhighlight lang=bash> | ||
#!/bin/sh | #!/bin/sh | ||
Line 97: | Line 117: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Notice the different actions for each argument in the case statement. The <code>start</code> and <code>stop</code> blocks will be run directly during the boot and shutdown processes based on the location of the 'S' and 'K' links to this script. The <code>restart</code> and <code>reload</code> options are additional controls that are provided by many init scripts to | + | Notice the different actions for each argument in the case statement. The <code>start</code> and <code>stop</code> blocks will be run directly during the boot and shutdown processes based on the location of the 'S' and 'K' links to this script. The <code>restart</code> and <code>reload</code> options are additional controls that are provided by many init scripts to make it easier to manually restart a process on a running system. For example, to restart the <code>busybox-httpd</code> server, you would run the command: |
− | + | ||
+ | <syntaxhighlight lang="text"> | ||
+ | root@emac-oe:~# /etc/init.d/busybox-httpd restart | ||
+ | </syntaxhighlight> | ||
+ | |||
This would effectively stop the server and then start it again. This is generally useful for forcing reconfiguration after configuration file changes are made without needing to reboot the system. | This would effectively stop the server and then start it again. This is generally useful for forcing reconfiguration after configuration file changes are made without needing to reboot the system. | ||
The <code>start-stop-daemon</code> can be used to control the initialization and termination of the application as illustrated in the <code>busybox-httpd</code> initscript above. The available options for the busybox version of the <code>start-stop-daemon</code> included with EMAC OE are shown below. | The <code>start-stop-daemon</code> can be used to control the initialization and termination of the application as illustrated in the <code>busybox-httpd</code> initscript above. The available options for the busybox version of the <code>start-stop-daemon</code> included with EMAC OE are shown below. | ||
− | + | ||
− | + | <syntaxhighlight lang=text> | |
− | + | BusyBox v1.13.2 (2009-06-24 18:00:48 CDT) multi-call binary | |
− | + | ||
− | + | Usage: start-stop-daemon [OPTIONS] [-S|-K] ... [-- arguments...] | |
− | + | ||
− | + | Search for matching processes, and then | |
− | + | -K: stop all matching processes. | |
− | + | -S: start a process unless a matching process is found. | |
− | + | ||
− | + | Process matching: | |
− | + | -u,--user USERNAME|UID Match only this user's processes | |
− | + | -n,--name NAME Match processes with NAME | |
− | + | in comm field in /proc/PID/stat | |
− | + | -x,--exec EXECUTABLE Match processes with this command | |
− | + | in /proc/PID/cmdline | |
− | + | -p,--pidfile FILE Match a process with PID from the file | |
− | + | All specified conditions must match | |
− | + | -S only: | |
− | + | -x,--exec EXECUTABLE Program to run | |
− | + | -a,--startas NAME Zeroth argument | |
− | + | -b,--background Background | |
− | + | -N,--nicelevel N Change nice level | |
− | + | -c,--chuid USER[:[GRP]] Change to user/group | |
− | + | -m,--make-pidfile Write PID to the pidfile specified by -p | |
− | + | -K only: | |
− | + | -s,--signal SIG Signal to send | |
− | + | -t,--test Match only, exit with 0 if a process is found | |
− | + | Other: | |
− | + | -o,--oknodo Exit with status 0 if nothing is done | |
+ | -v,--verbose Verbose | ||
+ | -q,--quiet Quiet | ||
+ | </syntaxhighlight> | ||
=== Adding and Removing Scripts === | === Adding and Removing Scripts === | ||
− | A new or existing initscript can be added or removed from the start process by simply creating or destroying the symbolic links from the <code>/etc/rc*.d/</code> directories. A utility application, <code>update-rc.d</code> is provided to automate this process. The usage of <code>update-rc.d</code> is shown below: | + | A new or existing initscript can be added or removed from the start process by simply creating or destroying the symbolic links from the <code>/etc/rc*.d/</code> directories. A utility application, <code>update-rc.d</code> , is provided to automate this process. The usage of <code>update-rc.d</code> is shown below: |
− | + | ||
+ | <syntaxhighlight lang="text"> | ||
+ | usage: update-rc.d [-n] [-f] [-r <root>] <basename> remove | ||
update-rc.d [-n] [-r <root>] [-s] <basename> defaults [NN | sNN kNN] | update-rc.d [-n] [-r <root>] [-s] <basename> defaults [NN | sNN kNN] | ||
update-rc.d [-n] [-r <root>] [-s] <basename> start|stop NN runlvl [runlvl] [...] . | update-rc.d [-n] [-r <root>] [-s] <basename> start|stop NN runlvl [runlvl] [...] . | ||
Line 142: | Line 171: | ||
-r: alternate root path (default is /) | -r: alternate root path (default is /) | ||
-s: invoke start methods if appropriate to current runlevel | -s: invoke start methods if appropriate to current runlevel | ||
+ | </syntaxhighlight> | ||
The <code>update-rc.d</code> utility can be used to add or remove the startup links for any initscript in the system. For example, the <code>/etc/init.d/busybox-httpd</code> script has the following links to it in the boot process: | The <code>update-rc.d</code> utility can be used to add or remove the startup links for any initscript in the system. For example, the <code>/etc/init.d/busybox-httpd</code> script has the following links to it in the boot process: | ||
− | + | ||
− | + | <syntaxhighlight lang="text"> | |
− | + | /etc/rc0.d/K20busybox-httpd | |
− | + | /etc/rc1.d/K20busybox-httpd | |
− | + | /etc/rc2.d/S20busybox-httpd | |
− | + | /etc/rc3.d/S20busybox-httpd | |
− | + | /etc/rc4.d/S20busybox-httpd | |
+ | /etc/rc5.d/S20busybox-httpd | ||
+ | /etc/rc6.d/K20busybox-httpd | ||
+ | </syntaxhighlight> | ||
+ | |||
Removing the links from the system startup without actually removing the <code>/etc/init.d/busybox-httpd</code> file will effectively disable the daemon from running at system startup or shutdown. To accomplish this, use the <code>remove</code> argument to <code>update-rc.d</code> as illustrated below: | Removing the links from the system startup without actually removing the <code>/etc/init.d/busybox-httpd</code> file will effectively disable the daemon from running at system startup or shutdown. To accomplish this, use the <code>remove</code> argument to <code>update-rc.d</code> as illustrated below: | ||
− | + | ||
− | + | <syntaxhighlight lang="text"> | |
− | + | root@emac-oe:~# update-rc.d -f busybox-httpd remove | |
− | + | ||
− | + | update-rc.d: /etc/init.d/busybox-httpd exists during rc.d purge (continuing) | |
− | + | Removing any system startup links for busybox-httpd ... | |
− | + | /etc/rc0.d/K20busybox-httpd | |
− | + | /etc/rc1.d/K20busybox-httpd | |
− | + | /etc/rc2.d/S20busybox-httpd | |
− | + | /etc/rc3.d/S20busybox-httpd | |
+ | /etc/rc4.d/S20busybox-httpd | ||
+ | /etc/rc5.d/S20busybox-httpd | ||
+ | /etc/rc6.d/K20busybox-httpd | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
{{mbox | type = notice | text = The <code>-f</code> argument is required in this case to "force" the links to be removed while the <code>/etc/init.d/busybox-httpd</code> still exists.}} | {{mbox | type = notice | text = The <code>-f</code> argument is required in this case to "force" the links to be removed while the <code>/etc/init.d/busybox-httpd</code> still exists.}} | ||
To add the links for the <code>/etc/init.d/busybox-httpd</code> script back into the system, the <code>defaults</code> argument may be used. Alternatively, the start and stop number for each runlevel may be specified explicitly as shown in the example below. Both methods will yield exactly the same results in this case; the runlevels are specified in this example simply to demonstrate the syntax. Using this method is required when it is important that a script starts at a specific point in the init process such as directly after networking is started. | To add the links for the <code>/etc/init.d/busybox-httpd</code> script back into the system, the <code>defaults</code> argument may be used. Alternatively, the start and stop number for each runlevel may be specified explicitly as shown in the example below. Both methods will yield exactly the same results in this case; the runlevels are specified in this example simply to demonstrate the syntax. Using this method is required when it is important that a script starts at a specific point in the init process such as directly after networking is started. | ||
− | + | ||
− | + | <syntaxhighlight lang="text"> | |
− | + | root@emac-oe:~# update-rc.d busybox-httpd start 20 2 3 4 5 . stop 20 0 1 6 . | |
− | + | ||
− | + | Adding system startup for /etc/init.d/busybox-httpd ... | |
− | + | /etc/rc2.d/S20busybox-httpd -> ../init.d/busybox-httpd | |
− | + | /etc/rc3.d/S20busybox-httpd -> ../init.d/busybox-httpd | |
− | + | /etc/rc4.d/S20busybox-httpd -> ../init.d/busybox-httpd | |
− | + | /etc/rc5.d/S20busybox-httpd -> ../init.d/busybox-httpd | |
+ | /etc/rc0.d/K20busybox-httpd -> ../init.d/busybox-httpd | ||
+ | /etc/rc1.d/K20busybox-httpd -> ../init.d/busybox-httpd | ||
+ | /etc/rc6.d/K20busybox-httpd -> ../init.d/busybox-httpd | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Temporarily Disabling Scripts === | ||
+ | |||
+ | Sometimes it is necessary to disable an initscript temporarily during development. The easiest way to disable a script from running is moving it out of the <code>/etc/init.d</code> directory. This will disable the script from being run at any runlevel. All of the symbolic links will be retained but will have no effect until the script is moved back into <code>/etc/init.d</code> | ||
+ | |||
+ | For example to disable the launching of the Xserver during boot: | ||
+ | <syntaxhighlight lang="text"> | ||
+ | root@emac-oe:~# cd /etc/init.d | ||
+ | root@emac-oe:/etc/init.d# mkdir disabled | ||
+ | root@emac-oe:/etc/init.d# mv xserver-nodm disabled/ | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | This will prevent any of the runlevels from launching the Xserver. | ||
+ | To re-enable the script: | ||
+ | <syntaxhighlight lang="text"> | ||
+ | root@emac-oe:~# cd /etc/init.d | ||
+ | root@emac-oe:/etc/init.d# mv disabled/xserver-nodm . | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Summary === | ||
+ | |||
+ | System V Initialization is used on EMAC OE filesystems and can be easily modified to alter the boot process. Configuring the <code>/etc/inittab</code> file allows users to define the initscripts run at various runlevels. The system init and runlevels are associated with directories containing symbolic links to scripts in <code>/etc/init.d</code>. The names of the links determine the action and order in which the scripts are run. Users can write simple initscripts and store them in <code>/etc/init.d/</code> to launch custom applications. These scripts can be linked to in various runlevels in order to start and stop the applications according to the requirements of the application. | ||
+ | |||
+ | For more information:<br /> | ||
+ | [http://en.wikipedia.org/wiki/Init Wikipedia Init Page]<br /> | ||
+ | [http://www.tldp.org/LDP/intro-linux/html/sect_04_02.html The Linux Documentation Project] | ||
== Custom Initialization == | == Custom Initialization == | ||
− | In some designs, the target application is so specific that only one main task will be performed. After a custom application has been developed and tested, it may be possible to simplify the boot process significantly by modifying the System V Init configuration. The end result is generally a | + | In some designs, the target application is so specific that only one main task will be performed. After a custom application has been developed and tested, it may be possible to simplify the boot process significantly by modifying the System V Init configuration. The end result is generally a much faster boot time. It is also possible to override <code>init</code> completely by changing the kernel boot argument value for <code>init</code>, but this method offers little benefit over the customized configuration described in this document. |
+ | |||
+ | A complete customization of the <code>inittab</code> file involves overriding the <code>/etc/init.d/rc</code> and <code>/etc/init.d/rcS</code> scripts altogether. A single script is specified for init to run during boot that performs the entire system initialization. The example <code>/etc/inittab</code> below will start the script <code>/etc/init.d/custom</code> and also start a serial console for login. | ||
+ | |||
+ | <syntaxhighlight lang="text"> | ||
+ | id:1:initdefault: | ||
+ | |||
+ | rc::bootwait:/etc/init.d/custom | ||
+ | # Serial console on ttyS0 | ||
+ | S:1:respawn:/sbin/getty 115200 ttyS0 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | === Example Custom Scripts === | ||
+ | The contents of the custom initialization script will vary depending on the system configuration and services required for the application. | ||
− | === | + | ==== Minimal Initialization ==== |
− | + | The following example is a simple custom initialization script that mounts the sysfs and procfs filesystems, configures a static networking interface, and starts a custom application. | |
− | + | <syntaxhighlight lang=bash> | |
− | + | #!/bin/sh | |
+ | |||
+ | # mount procfs and sysfs | ||
+ | if [ -e /proc ] && ! [ -e /proc/mounts ]; then | ||
+ | mount -t proc proc /proc | ||
+ | fi | ||
+ | if [ -e /sys ] && grep -q sysfs /proc/filesystems; then | ||
+ | mount sysfs /sys -t sysfs | ||
+ | fi | ||
+ | |||
+ | # configure networking | ||
+ | ifconfig lo 127.0.0.1 up | ||
+ | ifconfig eth0 10.0.2.41 netmask 255.255.255.0 up | ||
+ | |||
+ | # start custom application | ||
+ | /usr/bin/custom-application & | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ==== Advanced Initialization ==== | ||
+ | The example provided in this section is designed to do a significant amount of initialization while providing a fast boot time. Where possible, tasks are performed in the background to allow the script to continue execution. Any command or function called with an <code>&</code> at the end of the line will be run in the background. After the primary system initialization is completed, a custom application is executed followed by some final initialization such as starting the SSH server. | ||
+ | |||
+ | <syntaxhighlight lang=bash> | ||
+ | #!/bin/busybox sh | ||
+ | |||
+ | sysfs_init() | ||
+ | { | ||
+ | if [ -e /proc ] && ! [ -e /proc/mounts ]; then | ||
+ | /bin/mount -t proc proc /proc | ||
+ | fi | ||
+ | |||
+ | if [ -e /sys ] && grep -q sysfs /proc/filesystems; then | ||
+ | /bin/mount sysfs /sys -t sysfs | ||
+ | fi | ||
+ | } | ||
+ | |||
+ | alignment_init() | ||
+ | { | ||
+ | if [ -e /proc/cpu/alignment ]; then | ||
+ | echo "3" > /proc/cpu/alignment | ||
+ | fi | ||
+ | } | ||
+ | |||
+ | hostname_init() | ||
+ | { | ||
+ | if [ -f /etc/hostname ] | ||
+ | then | ||
+ | /bin/hostname -F /etc/hostname | ||
+ | fi | ||
+ | } | ||
+ | |||
+ | delayed_init() | ||
+ | { | ||
+ | /etc/init.d/modutils.sh start | ||
+ | /etc/init.d/sshd start | ||
+ | /etc/init.d/syslog start | ||
+ | } | ||
+ | |||
+ | network_init() | ||
+ | { | ||
+ | /etc/init.d/networking start >/dev/null | ||
+ | } | ||
+ | |||
+ | mount_init() | ||
+ | { | ||
+ | /bin/mount -a | ||
+ | } | ||
− | + | volatiles_init() | |
− | + | { | |
− | + | if [ -f /etc/volatile.cache ] | |
− | + | then | |
− | + | busybox sh /etc/volatile.cache | |
− | + | else | |
+ | /etc/init.d/populate-volatile.sh | ||
+ | fi | ||
+ | } | ||
− | + | misc_init() | |
− | + | { | |
+ | if [ -x "/sbin/sysctl" ] && [ -f "/etc/sysctl.conf" ] | ||
+ | then | ||
+ | /sbin/sysctl -p /etc/sysctl.conf | ||
+ | fi | ||
+ | /sbin/ldconfig | ||
+ | } | ||
+ | sysfs_init | ||
+ | alignment_init | ||
+ | mount_init | ||
+ | volatiles_init | ||
+ | hostname_init | ||
+ | network_init & | ||
+ | misc_init & | ||
+ | # Start custom app | ||
+ | /usr/bin/custom-application & | ||
+ | delayed_init >/dev/null | ||
+ | </syntaxhighlight> | ||
− | [[Category:Linux]] | + | <!--[[Category:Linux]] |
− | [[Category:OpenEmbedded]] | + | [[Category:OpenEmbedded]]--> |
Latest revision as of 15:06, 10 April 2014
When designing an embedded system, it is often necessary to add or remove applications and tasks from the system initialization sequence. This guide describes the initialization method used for EMAC OE systems and provides information on customizing the boot process.
Contents
System V Initialization
EMAC OE uses the System V Initialization method. This is a simple method for system initialization using a set of scripts run in sequential order. When the kernel has finished loading, /sbin/init
is started to initialize the userspace services in the system.
Runlevels
System V Init uses different runlevels to control the boot process. Each runlevel is associated with a set of scripts that are run sequentially to start various services on the system. The default runlevel on EMAC OE systems is 5. This is set in /etc/inittab
with the line:
# The default runlevel.
id:5:initdefault:
There are a total of seven runlevels available in System V Init, labeled 0 through 6. Runlevel 5 is the full user level in EMAC OE systems, regardless of whether a GUI is installed on the board or not. Runlevel 0 halts the system, and runlevel 6 is used for reboot. The other runlevels can be used for other purposes if desired configuring different levels of user functionality in each runlevel.
During boot, the scripts /etc/init.d/rcS
and /etc/init.d/rc
are executed to launch the scripts in /etc/rcS.d/
followed by the scripts in /etc/rc5.d/
(assuming that 5 is the default runlevel). The /etc/rcS.d/
and /etc/rc5.d/
directories contain a set of symbolic links starting with 'S'. These links are used to run scripts stored in /etc/init.d/
in a prescribed order. All of these startup scripts are passed the argument start
. During halt or reboot, the scripts in /etc/rc0.d/
or /etc/rc6.d/
starting with a 'K' are run in lexicographic order with the argument stop
.
To control the order in which the scripts are run, each symbolic link contains a number 00-99 immediately after the 'S' or 'K'. Symbolic links with the same numeric prefix will be run in alphanumeric order. For example, the listing below illustrates the files in /etc/rcS.d/
that will be run in order before entering the default runlevel:
root@emac-oe:/etc/rcS.d# ls
S02banner S20modutils.sh S40networking
S03sysfs S30ramdisk S41ifplugd
S03udev S35mountall.sh S45mountnfs.sh
S05devices S37populate-volatile.sh S55bootmisc.sh
S06alignment S38devpts.sh S98ipkg-configure
S10checkroot S39hostname.sh S99finish.sh
The action to perform at each level is specified in /etc/inittab
. For example, the following lines are used to trigger the execution of the /etc/init.d/rcS
and /etc/init.d/rc
scripts:
si::sysinit:/etc/init.d/rcS
....
l5:5:wait:/etc/init.d/rc 5
....
Initscripts
The directory /etc/init.d/
holds all of the initialization scripts that are run by init during boot or shutdown. These scripts should be designed to accept at least three arguments: start
, stop
, or restart
. As described in the previous section, /etc/rc*.d/
directories contain symbolic links to the scripts in /etc/init.d/
. This structure allows for easy modification of the boot process and the ability for a script to be run at different places in different runlevels. The detailed listing of the /etc/rcS.d/
directory is shown below:
root@emac-oe:/etc/rcS.d# ls -l
lrwxrwxrwx 1 root root 16 Dec 31 1969 S02banner -> ../init.d/banner
lrwxrwxrwx 1 root root 18 Dec 31 1969 S03sysfs -> ../init.d/sysfs.sh
lrwxrwxrwx 1 root root 14 Dec 31 1969 S03udev -> ../init.d/udev
lrwxrwxrwx 1 root root 17 Dec 31 1969 S05devices -> ../init.d/devices
lrwxrwxrwx 1 root root 22 Dec 31 1969 S06alignment -> ../init.d/alignment.sh
lrwxrwxrwx 1 root root 19 Dec 31 1969 S10checkroot -> ../init.d/checkroot
lrwxrwxrwx 1 root root 21 Dec 31 1969 S20modutils.sh -> ../init.d/modutils.sh
lrwxrwxrwx 1 root root 17 Dec 31 1969 S30ramdisk -> ../init.d/ramdisk
lrwxrwxrwx 1 root root 21 Dec 31 1969 S35mountall.sh -> ../init.d/mountall.sh
lrwxrwxrwx 1 root root 30 Dec 31 1969 S37populate-volatile.sh -> ../init.d/populate-volatile.sh
lrwxrwxrwx 1 root root 19 Dec 31 1969 S38devpts.sh -> ../init.d/devpts.sh
lrwxrwxrwx 1 root root 21 Dec 31 1969 S39hostname.sh -> ../init.d/hostname.sh
lrwxrwxrwx 1 root root 20 Dec 31 1969 S40networking -> ../init.d/networking
lrwxrwxrwx 1 root root 17 Dec 31 1969 S41ifplugd -> ../init.d/ifplugd
lrwxrwxrwx 1 root root 21 Dec 31 1969 S45mountnfs.sh -> ../init.d/mountnfs.sh
lrwxrwxrwx 1 root root 21 Dec 31 1969 S55bootmisc.sh -> ../init.d/bootmisc.sh
lrwxrwxrwx 1 root root 24 Dec 31 1969 S98ipkg-configure -> ../init.d/ipkg-configure
lrwxrwxrwx 1 root root 19 Dec 31 1969 S99finish.sh -> ../init.d/finish.sh
The other boot scripts on the system can be used as examples when creating custom initscripts. The application that is being started should be stored in the system PATH
, such as /usr/bin/
, and started from the script. For example, the busybox-httpd
initscript is shown below.
#!/bin/sh
DAEMON=/usr/sbin/httpd
NAME=httpd
DESC="Busybox HTTP Daemon"
#HTTPROOT="/srv/www"
HTTPROOT="/home/www"
ARGS="-h $HTTPROOT"
test -f $DAEMON || exit 0
set -e
case "$1" in
start)
echo -n "starting $DESC: $NAME... "
if [ ! -d $HTTPROOT ]; then
echo "$HTTPROOT is missing."
exit 1
fi
start-stop-daemon -S -b -n $NAME -a $DAEMON -- $ARGS
echo "done."
;;
stop)
echo -n "stopping $DESC: $NAME... "
start-stop-daemon -K -n $NAME
echo "done."
;;
restart)
echo "restarting $DESC: $NAME... "
$0 stop
$0 start
echo "done."
;;
reload)
echo -n "reloading $DESC: $NAME... "
killall -HUP $(basename ${DAEMON})
echo "done."
;;
*)
echo "Usage: $0 {start|stop|restart|reload}"
exit 1
;;
esac
exit 0
Notice the different actions for each argument in the case statement. The start
and stop
blocks will be run directly during the boot and shutdown processes based on the location of the 'S' and 'K' links to this script. The restart
and reload
options are additional controls that are provided by many init scripts to make it easier to manually restart a process on a running system. For example, to restart the busybox-httpd
server, you would run the command:
root@emac-oe:~# /etc/init.d/busybox-httpd restart
This would effectively stop the server and then start it again. This is generally useful for forcing reconfiguration after configuration file changes are made without needing to reboot the system.
The start-stop-daemon
can be used to control the initialization and termination of the application as illustrated in the busybox-httpd
initscript above. The available options for the busybox version of the start-stop-daemon
included with EMAC OE are shown below.
BusyBox v1.13.2 (2009-06-24 18:00:48 CDT) multi-call binary
Usage: start-stop-daemon [OPTIONS] [-S|-K] ... [-- arguments...]
Search for matching processes, and then
-K: stop all matching processes.
-S: start a process unless a matching process is found.
Process matching:
-u,--user USERNAME|UID Match only this user's processes
-n,--name NAME Match processes with NAME
in comm field in /proc/PID/stat
-x,--exec EXECUTABLE Match processes with this command
in /proc/PID/cmdline
-p,--pidfile FILE Match a process with PID from the file
All specified conditions must match
-S only:
-x,--exec EXECUTABLE Program to run
-a,--startas NAME Zeroth argument
-b,--background Background
-N,--nicelevel N Change nice level
-c,--chuid USER[:[GRP]] Change to user/group
-m,--make-pidfile Write PID to the pidfile specified by -p
-K only:
-s,--signal SIG Signal to send
-t,--test Match only, exit with 0 if a process is found
Other:
-o,--oknodo Exit with status 0 if nothing is done
-v,--verbose Verbose
-q,--quiet Quiet
Adding and Removing Scripts
A new or existing initscript can be added or removed from the start process by simply creating or destroying the symbolic links from the /etc/rc*.d/
directories. A utility application, update-rc.d
, is provided to automate this process. The usage of update-rc.d
is shown below:
usage: update-rc.d [-n] [-f] [-r <root>] <basename> remove
update-rc.d [-n] [-r <root>] [-s] <basename> defaults [NN | sNN kNN]
update-rc.d [-n] [-r <root>] [-s] <basename> start|stop NN runlvl [runlvl] [...] .
-n: not really
-f: force
-r: alternate root path (default is /)
-s: invoke start methods if appropriate to current runlevel
The update-rc.d
utility can be used to add or remove the startup links for any initscript in the system. For example, the /etc/init.d/busybox-httpd
script has the following links to it in the boot process:
/etc/rc0.d/K20busybox-httpd
/etc/rc1.d/K20busybox-httpd
/etc/rc2.d/S20busybox-httpd
/etc/rc3.d/S20busybox-httpd
/etc/rc4.d/S20busybox-httpd
/etc/rc5.d/S20busybox-httpd
/etc/rc6.d/K20busybox-httpd
Removing the links from the system startup without actually removing the /etc/init.d/busybox-httpd
file will effectively disable the daemon from running at system startup or shutdown. To accomplish this, use the remove
argument to update-rc.d
as illustrated below:
root@emac-oe:~# update-rc.d -f busybox-httpd remove
update-rc.d: /etc/init.d/busybox-httpd exists during rc.d purge (continuing)
Removing any system startup links for busybox-httpd ...
/etc/rc0.d/K20busybox-httpd
/etc/rc1.d/K20busybox-httpd
/etc/rc2.d/S20busybox-httpd
/etc/rc3.d/S20busybox-httpd
/etc/rc4.d/S20busybox-httpd
/etc/rc5.d/S20busybox-httpd
/etc/rc6.d/K20busybox-httpd
The -f argument is required in this case to "force" the links to be removed while the /etc/init.d/busybox-httpd still exists. |
To add the links for the /etc/init.d/busybox-httpd
script back into the system, the defaults
argument may be used. Alternatively, the start and stop number for each runlevel may be specified explicitly as shown in the example below. Both methods will yield exactly the same results in this case; the runlevels are specified in this example simply to demonstrate the syntax. Using this method is required when it is important that a script starts at a specific point in the init process such as directly after networking is started.
root@emac-oe:~# update-rc.d busybox-httpd start 20 2 3 4 5 . stop 20 0 1 6 .
Adding system startup for /etc/init.d/busybox-httpd ...
/etc/rc2.d/S20busybox-httpd -> ../init.d/busybox-httpd
/etc/rc3.d/S20busybox-httpd -> ../init.d/busybox-httpd
/etc/rc4.d/S20busybox-httpd -> ../init.d/busybox-httpd
/etc/rc5.d/S20busybox-httpd -> ../init.d/busybox-httpd
/etc/rc0.d/K20busybox-httpd -> ../init.d/busybox-httpd
/etc/rc1.d/K20busybox-httpd -> ../init.d/busybox-httpd
/etc/rc6.d/K20busybox-httpd -> ../init.d/busybox-httpd
Temporarily Disabling Scripts
Sometimes it is necessary to disable an initscript temporarily during development. The easiest way to disable a script from running is moving it out of the /etc/init.d
directory. This will disable the script from being run at any runlevel. All of the symbolic links will be retained but will have no effect until the script is moved back into /etc/init.d
For example to disable the launching of the Xserver during boot:
root@emac-oe:~# cd /etc/init.d
root@emac-oe:/etc/init.d# mkdir disabled
root@emac-oe:/etc/init.d# mv xserver-nodm disabled/
This will prevent any of the runlevels from launching the Xserver. To re-enable the script:
root@emac-oe:~# cd /etc/init.d
root@emac-oe:/etc/init.d# mv disabled/xserver-nodm .
Summary
System V Initialization is used on EMAC OE filesystems and can be easily modified to alter the boot process. Configuring the /etc/inittab
file allows users to define the initscripts run at various runlevels. The system init and runlevels are associated with directories containing symbolic links to scripts in /etc/init.d
. The names of the links determine the action and order in which the scripts are run. Users can write simple initscripts and store them in /etc/init.d/
to launch custom applications. These scripts can be linked to in various runlevels in order to start and stop the applications according to the requirements of the application.
For more information:
Wikipedia Init Page
The Linux Documentation Project
Custom Initialization
In some designs, the target application is so specific that only one main task will be performed. After a custom application has been developed and tested, it may be possible to simplify the boot process significantly by modifying the System V Init configuration. The end result is generally a much faster boot time. It is also possible to override init
completely by changing the kernel boot argument value for init
, but this method offers little benefit over the customized configuration described in this document.
A complete customization of the inittab
file involves overriding the /etc/init.d/rc
and /etc/init.d/rcS
scripts altogether. A single script is specified for init to run during boot that performs the entire system initialization. The example /etc/inittab
below will start the script /etc/init.d/custom
and also start a serial console for login.
id:1:initdefault:
rc::bootwait:/etc/init.d/custom
# Serial console on ttyS0
S:1:respawn:/sbin/getty 115200 ttyS0
Example Custom Scripts
The contents of the custom initialization script will vary depending on the system configuration and services required for the application.
Minimal Initialization
The following example is a simple custom initialization script that mounts the sysfs and procfs filesystems, configures a static networking interface, and starts a custom application.
#!/bin/sh
# mount procfs and sysfs
if [ -e /proc ] && ! [ -e /proc/mounts ]; then
mount -t proc proc /proc
fi
if [ -e /sys ] && grep -q sysfs /proc/filesystems; then
mount sysfs /sys -t sysfs
fi
# configure networking
ifconfig lo 127.0.0.1 up
ifconfig eth0 10.0.2.41 netmask 255.255.255.0 up
# start custom application
/usr/bin/custom-application &
Advanced Initialization
The example provided in this section is designed to do a significant amount of initialization while providing a fast boot time. Where possible, tasks are performed in the background to allow the script to continue execution. Any command or function called with an &
at the end of the line will be run in the background. After the primary system initialization is completed, a custom application is executed followed by some final initialization such as starting the SSH server.
#!/bin/busybox sh
sysfs_init()
{
if [ -e /proc ] && ! [ -e /proc/mounts ]; then
/bin/mount -t proc proc /proc
fi
if [ -e /sys ] && grep -q sysfs /proc/filesystems; then
/bin/mount sysfs /sys -t sysfs
fi
}
alignment_init()
{
if [ -e /proc/cpu/alignment ]; then
echo "3" > /proc/cpu/alignment
fi
}
hostname_init()
{
if [ -f /etc/hostname ]
then
/bin/hostname -F /etc/hostname
fi
}
delayed_init()
{
/etc/init.d/modutils.sh start
/etc/init.d/sshd start
/etc/init.d/syslog start
}
network_init()
{
/etc/init.d/networking start >/dev/null
}
mount_init()
{
/bin/mount -a
}
volatiles_init()
{
if [ -f /etc/volatile.cache ]
then
busybox sh /etc/volatile.cache
else
/etc/init.d/populate-volatile.sh
fi
}
misc_init()
{
if [ -x "/sbin/sysctl" ] && [ -f "/etc/sysctl.conf" ]
then
/sbin/sysctl -p /etc/sysctl.conf
fi
/sbin/ldconfig
}
sysfs_init
alignment_init
mount_init
volatiles_init
hostname_init
network_init &
misc_init &
# Start custom app
/usr/bin/custom-application &
delayed_init >/dev/null