Because I just had to research this (right down to reading kernel source), here is how the Linux kernel handles its command line arguments.
(The kernel command line is set in the bootloader in various ways. Grub lets you edit it on the fly, assuming that you can interrupt grub in time before it autoboots your kernel.)
First, the kernel goes through all kernel options and handles them. In theory all of the kernel options are documented in Documentation/kernel-parameters.txt in the kernel source, but beware: on a modern system that boots using an initial ramfs, a number of these options are really handled by the initial boot process instead of the kernel.
(For example,
root=...
and
init=...
are handled by the initial boot process, because the initramfs
/init
is what actually mounts the root filesystem and starts the real init.)
For anything that is not a kernel option and does not have a '.' in its name (these are assumed to be unhandled module parameters), one of two things happen. If it is of the form 'a=b' or (I believe) 'a=', it's placed in the environment that will be passed to the initial user-level process (generally either
/init
from the initial ramfs or
/sbin/init
). If it doesn't look like an environment variable setting it becomes one of the command line arguments for the initial user-level process. Everything from the kernel command line also appears in
/proc/cmdline
.
Generally the initial user-level process then immediately reads and pseudo-parses
/proc/cmdline
, pulling out various options that it cares about. Depending on your distribution, it may or may not pay any attention to its command line arguments (and for an initial ramfs
/init
, may or may not pass them to
/sbin/init
). Generally they are at most passed to
/sbin/init
; initial ramfs processing usually prefers to read everything from
/proc/cmdline
(partly because everything winds up there regardless of its specific form).
(I say 'pseudo-parses' because
/init
may or may not handle things like quoted arguments.)
Some but not all distributions make use of the initial environment variables; for example, Fedora sets
$LANG
right from the moment of boot this way.
Sidebar: what some distributions do with init command line arguments
All of these are for when you have an initial ramfs with its own
/init
.
- Ubuntu 10.04's and 12.04's
/initpass command line arguments to Upstart's/sbin/initbut otherwise ignores them. What options/initaccepts is documented in theinitramfs-toolsmanpages. - Fedora 17's
/initappears to completely ignore command line arguments and does not pass them to systemd's/sbin/init. However, it appears that you can specify arguments in aninit=option along with the program to run (unlike Ubuntu, where it can only be an executable). What options/initaccepts is documented in thedracutmanpage.(I expect that this is true of Fedora 16 and earlier but I lack the energy to dig up a Fedora 16 initrd image, unpack it, and carefully read through its
/initjust to be sure.) - Red Hat Enterprise 5 is sufficiently old that I think it uses a somewhat different scheme to transition from the initial ramdisk to your root filesystem. Its initrd
/initcertainly doesn't seem to do anything with command line arguments.
These days initial ramdisk images are gzip'd CPIO archives, so they can be extracted with:
mkdir /tmp/unpack cd /tmp/unpack zcat /boot/init<whatever>.img | cpio -id
Reading
/tmp/unpack/init
is the most interesting thing to do, although it may be relatively opaque.