Linux启动流程 | kernel执行第一个init应用程序的实现原理

1. 概述

Linux系统启动过程中通过init_task创建0号idle进程。然后通过kernel_thread创建1号init进程。创建该进程时通过系统调用,在内核空间执行用户空间的/sbin/init程序,通过该程序产生出shell,并依赖init衍生出其他进程。通过top命令查看当前系统环境下的进程列表,可以发现1号进程的为{linuxrc} init

[root@iTOP-4412]# top
Mem: 26404K used, 948572K free, 0K shrd, 3199543672K buff, 0K cached
CPU:  0.0% usr  6.0% sys  0.0% nic 94.0% idle  0.0% io  0.0% irq  0.0% sirq
Load average: 0.00 0.00 0.00 1/78 162PID  PPID USER     STAT   VSZ %VSZ CPU %CPU COMMAND162   132 root     R     3264  0.3   0  4.5 top3     2 root     IW       0  0.0   0  1.5 [kworker/0:0]132     1 root     S     3268  0.3   2  0.0 -/bin/sh1     0 root     S     3264  0.3   2  0.0 {linuxrc} init
...

我们在kernel代码中会发现,创建1号init进程的方式,主要包括以下3种,如下图所示:

0f61a51d2858aa31c63a3738ff8e3499.png

2. 创建init进程的方式

2.1 ramdisk方式

在ramdisk环境下创建init进程时,需要在kernel CMDLINE中设置init程序的路径位置,如下所示:

CONFIG_CMDLINE="...root=/dev/ram rdinit=/sbin/init..."

在kernel代码中通过rdinit_setup()解析kernel CMDLINErdinit=字符串,赋值给全局变量ramdisk_execute_command

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);

当完成ramdisk_execute_command赋值后,在kernel_init_freeable()ramdisk_execute_command进行检查,若未检查到有效的字符串,则将ramdisk_execute_command赋值为/init。然后,对ramdisk_execute_command进行访问权限检查,若失败,则进行rootfs挂载。

static noinline void __init kernel_init_freeable(void)
{
...if (!ramdisk_execute_command)ramdisk_execute_command = "/init";if (ksys_access((const char __user *)ramdisk_execute_command, 0) != 0) {ramdisk_execute_command = NULL;prepare_namespace();}
...
}

ramdisk_execute_command检查成功,则进入kernel_init()中,执行指定的init程序。

static int __ref kernel_init(void *unused)
{int ret;kernel_init_freeable();...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);}
...
}

2.2 execute_command方式

通过kernel CMDLINE可以设定执行的init程序,例如:

CONFIG_CMDLINE="root=/dev/mmcblk1p2 rw console=ttySAC2,115200 init=/linuxrc rootwait"

在kernel代码中通过init_setup()解析命令行参数"init=",并赋值给execute_command

static int __init init_setup(char *str)
{unsigned int i;execute_command = str;...for (i = 1; i < MAX_INIT_ARGS; i++)argv_init[i] = NULL;return 1;
}
__setup("init=", init_setup);

最后,在kernel_init()中执行execute_command所指定的init程序。

static int __ref kernel_init(void *unused)
{
...if (execute_command) {ret = run_init_process(execute_command);if (!ret)return 0;panic("Requested init %s failed (error %d).",execute_command, ret);}
...panic("No working init found.  Try passing init= option to kernel. ""See Linux Documentation/admin-guide/init.rst for guidance.");
}

2.3 默认方式

若以上两种指定init程序的方式均以失败告终,那么内核代码kernel_init()会执行如下4个默认的init程序,若也失败,则内核上报panic。

static int __ref kernel_init(void *unused)
{...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.");
}



推荐阅读:

专辑|Linux文章汇总

专辑|程序人生

专辑|C语言

我的知识小密圈

关注公众号,后台回复「1024」获取学习资料网盘链接。

欢迎点赞,关注,转发,在看,您的每一次鼓励,我都将铭记于心~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464764.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

poj1484

简单题 View Code #include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>using namespace std;#define maxn 25int n, m, blow, power[maxn];bool on[maxn];void out(int a){int b m - a - 1;int x;for (int i 0; i < b; i…

西安下雪了,做了一个室内温度计

摘要&#xff1a;最近各地都在下雪&#xff0c;湖南湖北西安都下雪了。养热带花草和宠物的同学们需要多留意室内温度。下面教一个实用性强、制作简单的温度计。使用DS18B20温度传感器和OLED模块构建&#xff0c;这里使用的开发板是Arduino。本项目的源码和3D文件在后台回复&…

oci mysql_Oracle常用的OCI函数

欢迎进入Oracle社区论坛&#xff0c;与200万技术人员互动交流 >>进入 sword OCIEnvInit ( OCIEnv **envhpp, ub4 mode, size_t xtramemsz, dvoid **usrmempp ); 注&#xff1a; 在8i以后&#xff0c;可用OCIEnvCreate一个函数就可以初始化环境了&#xff0c;相当于OCIIni…

android mysql 图片_android sqlite添加图片到数据库

sqlite图片是怎么储存的呢&#xff1f;其实是二进制的方式存储的blob代表使用二进制储存 (更多类型参考&#xff1a;数据库简介)在创建表的地方,VALUE_PIC代表存储图片字段&#xff0c;blob代表这个字段是以二进制储存的。/*创建表语句 语句对大小写不敏感 create table 表名(字…

MCU为什么内部不集成晶振

01MCU为什么不集成晶振本文将用STM32代替MCU。原因1&#xff1a;早些年&#xff0c;芯片的生产制作工艺也许还不能够将晶振做进芯片内部&#xff0c;但是现在可以了。这个问题主要还是实用性和成本决定的。实用性&#xff1a;如果封装进入STM32内部&#xff0c;不利于不同客户更…

cad中怎么随意移动图形_cad中怎么随意移动图形_绘制CAD图纸的过程中CAD快捷键失灵了怎么办?...

很多人在使用笔记本绘制CAD图纸的过程中&#xff0c;当用到CAD快捷键的时候会发现部分CAD快捷键无法正常使用&#xff0c;比如按F8后并没有切换成正交状态&#xff0c;而是出来了连接投影仪的选项&#xff0c;而且其他的快捷键也无法使用了&#xff0c;如下图所示。在以前老的笔…

GitHub的嵌入式开源项目

来源&#xff1a;嵌入式大杂烩关于GitHub&#xff0c;可能很多人误以为这是互联网人的专属&#xff0c;其实并不是&#xff0c;那上面嵌入式相关的开源项目是有很多的。现分享一些高星开源项目&#xff08;像RT-Thread、AWTK等大家都熟知的就不介绍了&#xff09;&#xff1a;A…

项目开发日志:Build AssetBundle——SpriteAtlas(已解惑)

项目信息&#xff1a;平台-AndroidUnity编辑器版本-2018.2.5f1状况1&#xff1a;真机状况下引用到图集下的sprite的UI显示出错。&#xff08;图集被打成AB包且勾选了Include in Build&#xff09;.在我们的测试下发现了以下两个解决方案&#xff1a;&#xff08;当然我觉得第二…

Sangfor上网行为管理单点登录配置

单点登录功能介绍&#xff1a; 当用户成功登录到第三方认证服务器时&#xff0c;自动通过AC的认证&#xff0c;而无需再次输入用户名和密码。 优点&#xff1a; 用户只需要输入一次账号和密码&#xff0c;即可自动通过AC的认证&#xff0c;避免账号和密码的重复输入&#xff0c…

教你精确计算 I2C 上拉电阻阻值

I2C 总线能挂多少设备&#xff1f;理论上&#xff1a;7-bit address &#xff1a;2 的 7 次方&#xff0c;能挂 128 个设备。10-bit address &#xff1a;2 的 10 次方&#xff0c;能挂 1024 个设备。当然&#xff0c;要把预留设备地址去除&#xff0c;7 bit 协议规定了 8个预留…

原型设计+用户规格说明书

用户规格说明书 作业链接&#xff1a;https://edu.cnblogs.com/campus/fzzcxy/2016SE/homework/2180 原型模型设计工具&#xff1a; 墨刀 原型模型链接&#xff1a;https://modao.cc/app/6a5fcc03e409ffe37cfcdb9cb06914271744f131 学号1&#xff1a;362 何永康 学号2&#xff…

什么集成mysql_mysql集成部署

经常听说mysql数据库是集成在系统中&#xff0c;也一直不太明白集成的概念。今天才明白集成的概念就是将mysql所有的文件放到一个文件夹下放到系统中&#xff0c;也就是将mysql采用目录迁移部署的方式进行安装。在上一篇研究了mysql的数据存储结构之后&#xff0c;也研究了mysq…

一文让你了解RT-Thread

前言要学习一项新知识或新的技能&#xff0c;首先要对其有个初步了解&#xff0c;然后再逐步学习如何运用它。本文作为快速入门 RT-Thread 系列文章的第一篇&#xff0c;首先介绍一下&#xff0c;我当时是如何学习 RT-Thread 的&#xff0c;以及参与官方组织的活动的情况&#…

创建python虚拟环境

一 windows下如何构建虚拟环境如果系统中只有python2或只有python3&#xff0c;可以直接打开命令行&#xff0c;输入pip install virtualenv 来下载创建虚拟环境的包(如果提示pip不是内部命令&#xff0c;把python文件下的Scripts的文件路径加入计算机环境变量即可可) 1. 选择一…

电源开关上的 | 和 O 究竟代表了什么?

大家好,我是写代码的篮球球痴&#xff0c;转发张老师的一篇文章。几乎所有的电器、灯具和插座上只要带有电源开关必然会出现“|”和“O”两个符号。如果只看符号判断&#xff0c;“|”和“O”到底代表什么含义呢&#xff1f;能分清&#xff1a;哪个是电路联通&#xff0c;哪个是…

重庆大二学生花了6年写出了操作系统

一直以来&#xff0c;国内操作系统都是弱势的地方&#xff0c;可能是国情原因吧&#xff0c;事实上国内也有不少人想改变这种格局&#xff0c;一直以来&#xff0c;笔者的朋友也在一直为这个方向努力&#xff0c;xbook内核&#xff0c;作者花了6年时间&#xff0c;从初中开始就…

辉哥给rockchip修复了一个内存溢出问题

还是周末我也不想说周末&#xff0c;但是不是周末的话&#xff0c;可能也没有特别清净的时间来处理困难的问题。这周末我是要加班的&#xff0c;加班的前一个晚上&#xff0c;我领导找我们吃了一个便饭&#xff0c;聊了很多东西&#xff0c;这篇文章我就不说了&#xff0c;会在…

MVC(dotnet)

一天中吹牛的时间到了&#xff0c;纠正一下自己的思维&#xff0c;要是能让过客收益那是我的荣幸。 前段时间就三层&MVC被一些网友搅的一头雾水....管他萝卜酸菜吃下去了才是自己的。 首先我要说明的是MVC只是一个表现模式&#xff0c;是一种软件架构模式&#xff0c;而三层…

微信小程序轮播图中间变大_微信小程序实现带放大效果的轮播图

本文实例为大家分享了微信小程序实现带放大效果的轮播图&#xff0c;供大家参考&#xff0c;具体内容如下效果如图WXMLWXSS.Carousel{margin-top: 49px;background-color: #fff;}.swiper-container{position: relative;}.swiper-container .swiper{padding-top: 8px;height: 38…

跟我领导吃饭

上篇文章说&#xff0c;下篇文章会说跟我们领导吃饭的事情。我领导是我上上上家公司的领导&#xff0c;不是现在TC的领导。自从离职后&#xff0c;我们差不多6个月没再见面&#xff0c;那时候我想跳槽&#xff0c;是因为得到消息说他要走&#xff0c;我刚开始不相信&#xff0c…