Init (User space boot) reference for Chaos Calmer: procd [OpenWrt Wiki]
Analysis of how the user space part of the boot sequence is implemented in OpenWrt, Chaos Calmer release.
On a fully booted Chaos Calmer system, pid 1 is /sbin/procd
:
root@openwrt:~# ps PID USER VSZ STAT COMMAND 1 root 1440 S /sbin/procd ...
At boot, Linux kernel starts /sbin/init
as the first user process. In Chaos Calmer, /sbin/init
does the preinit/failsafe steps, those that depend only on the read-only partition in flashed image, then execs (that is: is replaced by) /sbin/procd
to continue boot as specified by the configuration in writable flash partition. Procd started as pid 1 assumes several roles: service manager, hotplug events handler; this as of February 2016, when this research was done. Procd techref wiki page at this point in time is a design document and work in progress, if you are reading here and know/understand procd‘s semantics and API, please update that page.
Procd sources:
http://git.openwrt.org/?p=project/procd.git;a=tree;hb=0da5bf2ff222d1a499172a6e09507388676b5a08
at the commit used to build the procd package in Chaos Calmer release:
PKG_SOURCE_VERSION:=0da5bf2ff222d1a499172a6e09507388676b5a08
/sbin/init
source:
http://git.openwrt.org/?p=project/procd.git;a=blob;f=initd/init.c;hb=0da5bf2ff222d1a499172a6e09507388676b5a08#l71
This is the source code path followed in logical order of execution by the processor in user space while booting Chaos Calmer.
All links to source repositories should show the code at the commit used in Chaos Calmer release.
Pathnames evaluated at preinit time when / is read only have "(/rom)" prepended, to signify the path where the file is found on a fully booted system.
main(int argc, char **argv)
in /sbin/init, line 71early()
(definition)/proc
, /sys
, /sys/fs/cgroup
, /dev
(a tmpfs), /dev/pts
/dev
with entries from /sys/dev/{char;block}
/dev/console
as STDIN/STDOUT/STDERR/tmp
(optionally on zram), /tmp/run
, tmp/lock
, /tmp/state
/etc/fstab
is a broken symlink, line 161, with the following additions:procd_coldplug()
invoked at hotplug setup time will recreate /dev
from scratch./etc/rc.d/S10boot
will invoke mount_root
to setup a writable filesystem based on extroot or jffs2 overlay or a tmpfs backed snapshot capable overlay, add some directories and files, and mount debugfs./sbin/kmodloader (/rom)/etc/modules-boot.d/
kmodloader source/sbin/kmodloader
to probe the kernel modules declared in (/rom)/etc/modules-boot.d/
/rom/etc/…
when boot is done). The overlay filesystem is mounted later. kmodloader
main_loader()
(/rom)/etc/modules-boot.d/
, looking for lines starting with the name of a module to load, optionally followed by a space and module parameters. There appear to be special treatment for files with names beginning with a number: the modules they list are immediately loaded, then modules from files with name beginning with an ascii char greater than "9" are loaded all together in a final load_modprobe call.uloop_init()
line 116 (definition) int uloop_process_add(struct uloop_process *p)
p->pid
is the process id of a child process to monitor and p->cb
a pointer to a callback function.preinit()
line 117 (definition) /sbin/procd -h (/rom)/etc/hotplug-preinit.json
(/rom)/etc/rc.button/failsafe
/tmp/failsafe_button
containing the value of ${BUTTON}
is created if failsafe has been requested. PREINIT=1 /bin/sh (/rom)/etc/preinit
(/rom)/etc/preinit
with PREINIT=1
in its environment. Submits the child process to uloop management with the callback spawn_procd()
(/rom)/etc/preinit
./etc/preinit
(/rom)/lib/preinit
to build 5 lists of hooks and an environment, then run the hooks from some of the lists depending on the state of the environment. (/rom)/lib/preinit/80_mount_root
mount_root
/sbin/snapshot
script. The "SNAPSHOT=magic
" environment variable is set in mount_snapshot()
line 330.uloop_run()
, line 118(/rom)/etc/preinit
shell script, invokes the callback spawn_procd()setsid()
, line 67procd_signal()
, line 69 (definition), line 82.trigger_init()
, line 70 (definition)procd_state_next()
, line 74 (definition)state_enter(void)
used to sequence the remaining boot steps.STATE_EARLY
in state_enter()
hotplug("/etc/hotplug.json")
(definition)static char * rule_file;
.hotplug_handler()
on uevent arrival.hotplug_handler
callback stays active after coldplug, and will handle all uevents the kernel will emit.procd_coldplug()
(definition)/dev/pts
and /dev
, mounts a tmpfs on /dev
, creates directories /dev/shm
and /dev/pts
, forks udevtrigger
to reconstruct kernel uevents went unheard before netlink socket opening ("coldplug").udevtrigger
/sys/bus/*/devices
, /sys/class
; and /sys/block
if it isn‘t a subdir of /sys/class
, writing "add" to the uevent file of all devices. Then the kernel synthesizes an "add" uevent message on netlink. See Injecting events into hotplug via "uevent" in https://www.kernel.org/doc/pending/hotplug.txtudevtrigger_complete()
followed by coldplug_complete()
is attached to completion of the child udevtrigger process, such that the still to be reached uloop_run()
in procd main()
function, after all uevents will have been processed, will advance procd state to STATE_UBUS, line 31.uloop_run
, line 75/etc/hotplug.json
script/etc/rc.button/%BUTTON%
if the uevent has the "BUTTON
" value,/sbin/hotplug-call "%SUBSYSTEM%"
to handle all other subsystem related actions. int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
button-hotplug
gpio-button-hotplug
specific to OpenWrt. /sbin/hotplug-call "%SUBSYSTEM%"
/etc/hotlug.d/%SUBSYSTEM%/*
and sources all scripts assigned to a subsystem. "button" subsystem is handled here if the uevent lacks the "BUTTON" value, unlikely or impossible?.STATE_UBUS
procd_state_next
which results in advancing procd to STATE_UBUS./sbin/ubus
as the system ubus service.ubus_connect_cb
that at the end, line 118, calls procd_state_ubus_connect()
, line 186, that calls procd_state_next
to transition toSTATE_INIT
/etc/inittab
is parsed and entries ::askconsole:/bin/ash –login
::sysinit:/etc/init.d/rcS S boot
sysinit
action" handlerrunrc
rcdone
will advance procd state.runrc
ignores the process specification "/etc/init.d/rcS
" (there is no such a script!), and runsrcS(pattern="S" , param="boot", rcdone)
(line 159)_rc(&q, *path="/etc/rc.d", *file="S", *pattern="*", *param="boot")
/etc/rc.d/S* boot
boot
" as the action. /etc/rc.d/S*
are symlinks made by rc.common enable to files in /etc/init.d
, that are shell scripts with the shebang #!/bin/sh /etc/rc.common
./etc/rc.d/S*
script runs rc.common
that sources the /etc/rc.d/S* script to set up a context, then invokes the function named as the action parameter ("boot()
"), in that context.STATE_RUNNING
STATE_SHUTDOWN
OpenWRT Init (User space boot) reference for Chaos Calmer: procd
原文:http://www.cnblogs.com/merlindu/p/6478228.html