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_UBUSprocd_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 bootsysinit action" handlerrunrcrcdone 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* bootboot" 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_RUNNINGSTATE_SHUTDOWNOpenWRT Init (User space boot) reference for Chaos Calmer: procd
原文:http://www.cnblogs.com/merlindu/p/6478228.html