以linux4.19内核linux系统中第一个进程。
执行shell指令 ps -ef 结果如下:
xxx@xxx-virtual-machine:~$ ps -ef
UID          PID    PPID  C STIME TTY          TIME CMD
root           1       0  0 20:55 ?        00:00:02 /sbin/init splash
root           2       0  0 20:55 ?        00:00:00 [kthreadd]
root           3       2  0 20:55 ?        00:00:00 [rcu_gp]
root           4       2  0 20:55 ?        00:00:00 [rcu_par_gp]
root           5       2  0 20:55 ?        00:00:00 [slub_flushwq]
root           6       2  0 20:55 ?        00:00:00 [netns]
root           8       2  0 20:55 ?        00:00:00 [kworker/0:0H-events_highpri]
root          10       2  0 20:55 ?        00:00:00 [mm_percpu_wq]
root          11       2  0 20:55 ?        00:00:00 [rcu_tasks_rude_]
root          12       2  0 20:55 ?        00:00:00 [rcu_tasks_trace]
root          13       2  0 20:55 ?        00:00:00 [ksoftirqd/0]
root          14       2  0 20:55 ?        00:00:00 [rcu_sched]
root          15       2  0 20:55 ?        00:00:00 [migration/0]
root          16       2  0 20:55 ?        00:00:00 [idle_inject/0]
root          17       2  0 20:55 ?        00:00:00 [kworker/0:1-events]
root          18       2  0 20:55 ?        00:00:00 [cpuhp/0]
root          19       2  0 20:55 ?        00:00:00 [cpuhp/1]
root          20       2  0 20:55 ?        00:00:00 [idle_inject/1]
root          21       2  0 20:55 ?        00:00:00 [migration/1]
...
可以看到第一个进程PID为1,拉起第一个进程的指令为/sbin/init splash
内核启动流程:
 start_kernel (init/main.c)
 kernel_init
kernel_init函数如下:
static int __ref kernel_init(void *unused)
{...if (ramdisk_execute_command) {ret = run_init_process(ramdisk_execute_command);if (!ret)return 0;pr_err("Failed to execute %s (error %d)\n", ramdisk_execute_command, ret);}/** We try each of these until one succeeds.** The Bourne shell can be used instead of init if we are* trying to recover a really broken machine.*/if (execute_command) {ret = run_init_process(execute_command);if (!ret)return 0;panic("Requested init %s failed (error %d).",execute_command, ret);}if (!try_to_run_init_process("/sbin/init") ||!try_to_run_init_process("/etc/init") ||!try_to_run_init_process("/bin/init") ||!try_to_run_init_process("/bin/sh"))return 0;panic("No working init found.  Try passing init= option to kernel. ""See Linux Documentation/admin-guide/init.rst for guidance.");}
上面代码片中的两个变量:ramdisk_execute_command 和 execute_command。
 其定义如下:
static int __init init_setup(char *str)
{unsigned int i;execute_command = str;/** In case LILO is going to boot us with default command line,* it prepends "auto" before the whole cmdline which makes* the shell think it should execute a script with such name.* So we ignore all arguments entered _before_ init=... [MJ]*/for (i = 1; i < MAX_INIT_ARGS; i++)argv_init[i] = NULL;return 1;
}
__setup("init=", init_setup);static int __init rdinit_setup(char *str)
{unsigned int i;ramdisk_execute_command = str;/* See "auto" comment in init_setup */for (i = 1; i < MAX_INIT_ARGS; i++)argv_init[i] = NULL;return 1;
}
__setup("rdinit=", rdinit_setup);使用__setup("init=", init_setup)宏注册了这个函数,这样当内核启动时遇到
init=<command>这样的启动参数时,就会调用init_setup函数进行处理。
-  ramdisk_execute_command 
 ramdisk_execute_command 变量的值可以通过内核启动参数 rdinit 来设置。在Linux内核引导过程中,如果用户在命令行参数或GRUB等 bootloader配置中指定了类似 rdinit=/path/to/executable 的参数,内核在初始化initrd之后会尝试执行位于指定路径的可执行文件作为初始化脚本或进程。
-  execute_command 
 类似上面
