393 */
394 kernel_thread(kernel_init,NULL, CLONE_FS);
395 numa_default_policy();
396 pid = kernel_thread(kthreadd,NULL, CLONE_FS | CLONE_FILES);
397 rcu_read_lock();
398 kthreadd_task = find_task_by_pid_ns(pid,&init_pid_ns);
399 rcu_read_unlock();
400 complete(&kthreadd_done);
401
402/*
403 * The boot idle thread must execute schedule()
404 * at least once to get things moving:
405 */
406 init_idle_bootup_task(current);
407 schedule_preempt_disabled();
408/* Call into cpu_idle with preempt disabled */
409 cpu_startup_entry(CPUHP_ONLINE);
410}
第387行,调用函数rcu_scheduler_starting,启动RCU锁调度器
第394行,调用函数kernel_thread创建kernel_init线程,也就是大名鼎鼎的init内核进程 。init进程的PID为1 。init进程一开始是内核进程(也就是运行在内核态),后面init进程会在根文件系统中查找名为"init"这个程序,这个"init"程序处于用户态,通过运行这个"init"程序,init进程就会实现从内核态到用户态的转变 。
第396行,调用函数kernel_thread创建kthreadd内核进程,此内核进程的PID为2 。kthreadd进程负责所有内核进程的调度和管理 。
第409行,最后调用函数cpu_startup_entry来进入idle进程,cpu_startup_entry会调用cpu_idle_loop,cpu_idle_loop是个while循环,也就是idle进程代码 。idle进程的PID为0,idle进程叫做空闲进程,如果学过FreeRTOS或者UCOS的话应该听说过空闲任务 。idle空闲进程就和空闲任务一样,当CPU没有事情做的时候就在idle空闲进程里面"瞎逛游",反正就是给CPU找点事做 。当其他进程要工作的时候就会抢占idle进程,从而夺取CPU使用权 。其实大家应该可以看到idle进程并没有使用kernel_thread或者fork函数来创建,因为它是有主进程演变而来的 。
在Linux终端中输入"ps-A"就可以打印出当前系统中的所有进程,其中就能看到init进程和kthreadd进程,如图36.2.4.1所示:

文章插图
图36.2.4.1 Linux系统当前进程
从图36.2.4.1可以看出,init进程的PID为1,kthreadd进程的PID为2 。之所以图36.2.4.1中没有显示PID为0的idle进程,那是因为idle进程是内核进程 。我们接下来重点看一下init进程,kernel_init就是init进程的进程函数 。
36.2.5 init进程kernel_init函数就是init进程具体做的工作,定义在文件init/main.c中,函数内容如下:
示例代码36.2.5.1 kernel_init函数
928staticint __ref kernel_init(void*unused)
929{
930int ret;
931
932 kernel_init_freeable(); /* init进程的一些其他初始化工作 */
933/* need to finish all async __init code before freeing the
memory */
934 async_synchronize_full(); /* 等待所有的异步调用执行完成 */
935 free_initmem(); /* 释放init段内存 */
936 mark_rodata_ro();
937 system_state = SYSTEM_RUNNING;/* 标记系统正在运行 */
938 numa_default_policy();
939
940 flush_delayed_fput();
941
942if(ramdisk_execute_command){
943 ret = run_init_process(ramdisk_execute_command);
944if(!ret)
945return0;
946 pr_err("Failed to execute %s (error %d)\n",
947 ramdisk_execute_command, ret);
948}
949
950/*
951 * We try each of these until one succeeds.
952 *
953 * The Bourne shell can be used instead of init if we are
954 * trying to recover a really broken machine.
955 */
956if(execute_command){
957 ret = run_init_process(execute_command);
958if(!ret)
959return0;
960 panic("Requested init %s failed (error %d).",
961 execute_command, ret);
962}
- 淘宝直播严选可靠吗?有用吗?
- b站自媒体平台怎么注册?步骤介绍
- 守望先锋在哪个平台买 守望先锋测试服怎么进入
- 2023年京东特价版&京喜平台商家换签续费公告
- 2023年京东特价版&京喜开放平台京喜C店开店管理规则
- 2023年京东开放平台商家换签续费公告
- 2023年京东商家换签续费公告
- 寻宝平台 天天寻宝答案
- 抖音号交易平台有哪些?交易方式有哪些?
- 速卖通靠什么赚钱?速卖通平台怎么样?
特别声明:本站内容均来自网友提供或互联网,仅供参考,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
