When start_kernel forks out the
init thread (implemented by the
init function in
init/main.c
), it is still running in kernel mode,
and so is the init thread. When all
initializations described earlier are complete, the thread drops the
kernel lock and prepares to execute the user-space
init process. The file being executed
resides in /sbin/init
,
/etc/init
, or /bin/init
. If
none of those are found, /bin/sh
is run as a
recovery measure in case the real init got
lost or corrupted. As an alternative, the user can specify on the
kernel command line which file the init
thread should execute.
The procedure to enter user space is simple. The code opens
/dev/console
as standard input by calling the
open system call and connects the console to
stdout and stderr by calling
dup; it finally calls execve
to execute the user-space program.
The thread is able to invoke system calls while running in kernel mode
because init/main.c
has declared
__KERNEL_SYSCALLS__
before
including <asm/unistd.h>
. The header defines
special code that allows kernel code to invoke a limited number of
system calls just as if it were running in user space. More
information about kernel system calls can be found in
http://www.linux.it/kerneldocs/ksys.
The final call to execve finalizes the transition to user space. There is no magic involved in this transition. As with any execve call in Unix, this one replaces the memory maps of the current process with new memory maps defined by the binary file being executed (you should remember how executing a file means mapping it to the virtual address space of the current process). It doesn’t matter that, in this case, the calling process is running in kernel space. That’s transparent to the implementation of execve, which just finds that there are no previous memory maps to release before activating the new ones.
Whatever the system setup or command line, the init process is now executing in user space and any further kernel operation takes place in response to system calls coming from init itself or from the processes it forks out.
More information about how the init process brings up the whole system can be found in http://www.linux.it/kerneldocs/init. We’ll now proceed on our tour by looking at the system calls implemented in each source directory, and then at how device drivers are laid out and organized in the source tree.