【日常积累】Linux之init系统学习
init系统简介:
Linux 操作系统的启动首先从 BIOS 开始,接下来进入 boot loader,由 bootloader 载入内核,进行内核初始化。内核初始化的最后一步就是启动 pid 为 1 的 init 进程,这个进程是系统的第一个进程,它负责产生其他所有用户进程。
init 的一些特点
- init是Linux系统操作中不可缺少的程序之一。
- 所谓的init进程,它是由内核启动的第一个用户级进程。内核自行启动(已被装入内存,开始运行,并已初始化所有的设备驱动程序和数据结构等)之后,就通过启动一个用户级程序init的方式,完成引导进程。所以,init始终是第一个进程(其进程编号始终为1)。
- 仅仅将内核运行起来是毫无实际用途的,必须由 init 系统将系统代入可操作状态。比如启动外壳 shell 后,便有了人机交互,这样就可以让计算机执行一些预订程序完成有实际意义的任务(这其实就是就是后面所说的内核态到用户态的转变)。内核会在过去曾使用过init的几个地方查找它,它的正确位置(对Linux系统来说)是/sbin/init。如果内核找不到init,它就会试着运行/bin/sh,如果运行失败,系统的启动也会失败。
Linux下的三个特殊进程
Linux下有三个特殊的进程idle进程(PID=0),init进程(PID=1),和kthreadd(PID=2)
- idle进程由系统自动创建,运行在内核态。idle进程其pid=0,其前身是系统创建的第一个进程,也是唯一一个没有通过fork或者kernel_thread产生的进程。完成加载系统后,演变为进程调度、交换。
- kthreadd进程由idle通过kernel_thread创建,并始终运行在内核空间,负责所有内核进程的调度和管理。它的任务就是管理和调度其他内核线程kernel_thread, 会循环执行一个kthread的函数,该函数的作用就是运行kthread_create_list全局链表中维护的kthread, 当我们调用kernel_thread创建的内核线程会被加入到此链表中,因此所有的内核线程都是直接或者间接的以kthreadd为父进程 。
- init进程由idle通过kernel_thread创建,在内核空间完成初始化后,加载init程序。在这里我们就主要了解下init进程,init进程由0进程创建,完成系统的初始化,是系统中所有其他用户进程的祖先进程
Linux中的所有进程都是由init进程创建并运行的。首先Linux内核启动,然后在用户空间中启动init进程,再启动其他系统进程。在系统启动完成后,init将变成为守护进程监视系统其他进程。(内核态转变为用户态)
大致过程为:0号进程->1号内核进程->1号用户进程(init进程)->getty进程->shell进程
init进程完成从内核态向用户态的转变

一个进程先后两种状态
init进程刚开始运行的时候是内核态,它属于一个内核线程,然后运行一个用户态下面的程序后(如/sbin/init),把自己转成用户态(后面的进程需要工作在用户态下)。
init进程完成了从内核态到用户态的过渡,因此后续的其他进程都可以工作在用户态。
init进程在内核态下的工作内容
主要是挂载根文件系统,并试图找到用户态下的那个init程序。(这句话看出,init进程是早于init程序运行的。)
init进程要把自己转成用户态就必须运行一个用户态的应用程序,要运行这个应用程序就必须得找到这个应用程序,要找到这个应用程序就必须得挂载根文件系统,因为所有的应用程序都在文件系统中。
内核源代码中的所有函数都处于内核态,执行其中任何一个都不能脱离内核态。而应用程序必须不属于内核源代码,这样才能保证应用程序处于用户态。这里执行的init程序和内核不在一起,由根文件系统另外提供。
init进程在用户态下的工作内容
init进程大部分有意义的工作都是在用户态下进行的。init进程对操作系统的意义在于,其他所有的用户进程都直接或者间接派生自init进程。
init进程如何从内核态跳跃到用户态 ?还能回来不?
init进程处于内核态时,通过函数do_execve来执行一个用户空间编译链接的应用程序就跳跃到用户态了。
- 跳跃过程中进程号没有改变,一直是进程1。
- 跳跃过程是单向的,一旦执行init程序转到用户态,整个操作系统就算真正运转起来了,以后只能在用户态下工作,用户态下想要进入内核态只能通过调用API。
1、init进程挂载了根文件系统
(1)prepare_namespace函数挂载根文件系统。
(2)根文件系统在哪里?根文件系统的文件系统类型是什么?
uboot通过传参来告诉内核这些信息。
uboot传参中的root=/dev/mmcblk0p2 rw 这一句就是告诉内核根文件系统在哪里。
uboot传参中的rootfstype=ext3这一句就是告诉内核rootfs的类型。
(3)挂载结果
如果内核挂载根文件系统成功,则会打印出:VFS: Mounted root (ext3 filesystem) on device 179:2。(也可能其他数字)
如果挂载根文件系统失败,则会打印:No filesystem could mount root, tried: yaffs2
(4)如果内核启动时挂载rootfs失败,则后面无法执行。
内核中设置了启动失败休息5s自动重启的机制,因此这里会自动重启,所以有时候大家会看到反复重启的情况。
(5)如果挂载rootfs失败,可能的原因有
最常见的错误就是uboot的bootargs设置不对。
rootfs烧录失败(fastboot烧录不容易出错)。
rootfs本身制作失败的。
2、init进程执行init程序完成内核态到用户态的转变
(1)一旦挂载rootfs成功,则进入rootfs中寻找应用程序的init程序(在init_post()函数中),找到后用run_init_process去执行。
(2)如果确定init程序是谁?
先从uboot传参cmdline中看有没有指定,如果有指定先执行cmdline中指定的程序。比如init=/linuxrc表示rootfs的根目录下的linuxrc程序就是init程序。
如果uboot传参cmdline中没有init=xx或者cmdline中指定的这个xx执行失败,还有备用方案。第一备用:/sbin/init,第二备用:/etc/init,第三备用:/bin/init,第四备用:/bin/sh。如果以上都不成功,则没有办法了。
init=/linuxrc一般指向busybox。
3、init进程构建了用户交互界面
(1)init进程是其他用户进程的祖先。
linux系统中一个进程的创建是通过其父进程创建出来的。根据这个理论只要有一个父进程就能生出一堆子孙进程了。
(2)init启动了login进程(用户登录进程)、命令行进程(提供命令行环境)、shell进程(提供命令解释和执行)。
(3)shell进程启动了其他用户进程。
命令行和shell一旦工作,用户就可以在命令行下通过./xx的方式来执行其他应用程序,每一个应用程序的运行就是一个进程。
4、init进程打开了控制台
(1)linux系统中每个进程都有自己的一个文件描述符表,表中存储的是本进程打开的文件。
(2)linux系统中一切皆是文件,因此设备也是以文件的方式来访问的。要访问一个设备,就要打开此设备对应的文件描述符。譬如/dev/fb0这个设备文件就代表LCD显示器设备,/dev/buzzer代表蜂鸣器设备,/dev/console代表控制台设备。
(3)这里打开了/dev/console文件,并且复制了2次文件描述符,一共得到了3个文件描述符。这三个文件描述符分别是0、1、2,就是所谓的标准输入、标准输出、标准错误这3个文件描述符。
(4)进程1打开了这3个文件描述符,因此进程1衍生出来的所有的进程默认都具有这3个文件描述符。
运行级别
简单的说,运行级就是操作系统当前正在运行的功能级别。这个级别有多种,以centos为例,6和7版本的设置方法不同,具体对应关系如下。
| init level (centos 6 /etc/inittab) | systemctl target(centos 7) | 说明 |
|---|---|---|
| 0 | poweroff.target | 停机(千万不能把initdefault 设置为0 ) |
| 1 | rescure.target | 单用户(救援)模式 |
| 2 | multi-user.target | 多用户,没有 NFS |
| 3 | multi-user.target | 完整的多用户文本模式级别,登录后进入到控制台命令行模式 |
| 4 | 未使用 | |
| 5 | graphical.target | X11 (xwindow,能够正常切换的前提是系统支持) |
| 6 | reboot.target | 重新启动 |
[root@k8s-m1 ~]# ll /usr/lib/systemd/system/runlevel*target
lrwxrwxrwx 1 root root 15 Feb 27 16:14 /usr/lib/systemd/system/runlevel0.target -> poweroff.target
lrwxrwxrwx 1 root root 13 Feb 27 16:14 /usr/lib/systemd/system/runlevel1.target -> rescue.target
lrwxrwxrwx 1 root root 17 Feb 27 16:14 /usr/lib/systemd/system/runlevel2.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Feb 27 16:14 /usr/lib/systemd/system/runlevel3.target -> multi-user.target
lrwxrwxrwx 1 root root 17 Feb 27 16:14 /usr/lib/systemd/system/runlevel4.target -> multi-user.target
lrwxrwxrwx 1 root root 16 Feb 27 16:14 /usr/lib/systemd/system/runlevel5.target -> graphical.target
lrwxrwxrwx 1 root root 13 Feb 27 16:14 /usr/lib/systemd/system/runlevel6.target -> reboot.target
运行级别的配置
centos6设置默认的启动级别
# 查看运行级别: centos7 也可以使用该命令。[root@k8s-m1 ~]# runlevel N 3
# 修改运行级别:临时修改: init level(对应的级别即可)永久修改:需要修改 /etc/inittab 文件。
在最下面的一行中的语句 id:5:initdefault 中的数字5改成需要的启动程度就可以了,一般是命令行模式 3
centos7设置默认的启动级别
#centos7修改设置默认的系统级别
[root@k8s-m1 ~]# systemctl set-default multi-user.target
Removed symlink /etc/systemd/system/default.target.
Created symlink from /etc/systemd/system/default.target to /usr/lib/systemd/system/multi-user.target.
#centos7查看默认的系统级别
[root@k8s-m1 ~]# systemctl get-default multi-user.target
参考:https://blog.csdn.net/m0_45406092/article/details/130660743
更多关于Linux的知识请前往博客主页查看。
相关文章:
【日常积累】Linux之init系统学习
init系统简介: Linux 操作系统的启动首先从 BIOS 开始,接下来进入 boot loader,由 bootloader 载入内核,进行内核初始化。内核初始化的最后一步就是启动 pid 为 1 的 init 进程,这个进程是系统的第一个进程,它负责产生…...
Python功能制作之3D方块
介绍 用python写一个黑窗口,窗口里面有一个白色的3D方块,左键按下后移动可以旋转以各个视角来看方块。 当然有需要的话,可以自己在代码中去更改颜色,直接通过RBG的参数进行更改即可。 做了两个函数:init[初始化]和d…...
【0基础入门Python笔记】二、python 之逻辑运算和制流程语句
二、python 之逻辑运算和制流程语句 逻辑运算控制流程语句条件语句(if语句)循环结构(for循环、while循环)continue、break和pass关键字控制流程语句的嵌套以及elif 逻辑运算 Python提供基本的逻辑运算:不仅包括布尔运…...
python中的svm:介绍和基本使用方法
python中的svm:介绍和基本使用方法 支持向量机(Support Vector Machine,简称SVM)是一种常用的分类算法,可以用于解决分类和回归问题。SVM通过构建一个超平面,将不同类别的数据分隔开,使得正负样…...
typedef
t y p e d e f typedef typedef 声明,简称typedef,是创建现有类型的新名字。 比如: #include <bits/stdc.h> using namespace std; typedef long long ll; int main() {ll n;scanf("%lld",&n);printf("%lld"…...
校园跑腿市场行情分析
随着社会的发展和人们生活节奏的加快,校园跑腿市场逐渐兴起并呈现出蓬勃发展的态势。在这个快节奏的时代,越来越多的学生需要在繁忙的学业之外完成各种任务,而校园跑腿服务正是应运而生,为他们提供了便利和时效。本文将从需求方面…...
微服务相关面试题
👏作者简介:大家好,我是爱写博客的嗯哼,爱好Java的小菜坤 🔥如果感觉博主的文章还不错的话,请👍三连支持👍一下博主哦 📝社区论坛:希望大家能加入社区共同进步…...
前端-ES6
let 和 const 为了解决var的作用域的问题,而且var 有变量提升,会出现全局污染的问题 let 块状作用域,并且不能重复声明const 一般用于声明常量,一旦被声明无法修改,但是const 可以声明一个对象,对象内部的…...
169. 多数元素(摩尔投票法) 题解
题目描述:169. 多数元素 - 力扣(LeetCode) 给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示…...
python中的cnn:介绍和基本使用方法
python中的cnn:介绍和基本使用方法 卷积神经网络(Convolutional Neural Networks,简称CNN)是一种在图像识别、语音识别、自然语言处理等许多领域取得显著成功的深度学习模型。CNN的设计灵感来源于生物的视觉系统,由多…...
Dockerfile概念、镜像原理、制作及案例讲解
1.Docker镜像原理 Linux文件操作系统讲解 2.镜像如何制作 3.Dockerfile概念 Docker网址:https://hub.docker.com 3.1 Dockerfile关键字 4.案例...
07-微信小程序-注册页面-模块化
07-微信小程序-注册页面 文章目录 注册页面使用 Page 构造器注册页面参数Object初始数据案例代码 生命周期回调函数组件事件处理函数setData()案例代码 生命周期模块化 注册页面 对于小程序中的每个页面,都需要在页面对应的 js 文件中进行注册,指定页面…...
考研算法第46天: 字符串转换整数 【字符串,模拟】
题目前置知识 c中的string判空 string Count; Count.empty(); //正确 Count ! null; //错误c中最大最小宏 #include <limits.h>INT_MAX INT_MIN 字符串使用发运算将字符加到字符串末尾 string Count; string str "liuda"; Count str[i]; 题目概况 AC代码…...
Cesium for unity 1.5.0使用注意事项
Cesium for Unity Quickstart – Cesium 1.Unity版本仅支持Unity2021.3.2f1以后版 2.仅支持 3D (URP)和3D (HDRP)渲染管线 3.如果Package Manager中不出现My Registries选项,请在 Edit > Project Settings...>Package Manager中重命名或删除重新添加Packag…...
初阶C语言-结构体
🌞 “少年有梦不至于心动,更要付诸行动。” 今天我们一起学习一下结构体的相关内容! 结构体 🎈1.结构体的声明1.1结构的基础知识1.2结构的声明1.3结构成员的类型1.4结构体变量的定义和初始化 🎈2.结构体成员的访问2.1结…...
Android Studio实现解析HTML获取图片URL,将URL存到list,进行瀑布流展示
目录 效果展示build.gradle(app)添加的依赖(用不上的可以不加)AndroidManifest.xml错误代码activity_main.xmlitem_image.xmlMainActivityImage适配器ImageModel 接收图片URL效果展示 build.gradle(app)添加的依赖(用不上的可以不加) dependencies {implementation co…...
java学习004
常用数据结构对应 php中常用的数据结构是Array数组,相对的在java开发中常用的数据结构是ArrayList和HashMap,它们可以看成是array的拆分,一种简单的对应关系为 PHPJAVAArray: array(1,2,3)ArrayListlArray: array(“name” > “jack”,“…...
Linux网络编程:网络基础
文章目录: 1.协议 2.锁 3.网络层次模型 4.以太网帧和ARP协议 5.IP协议 6.UDP协议 7.TCP协议 8.BS模式和CS模式 9.网络套接字(socket) 10.网络字节序 11.IP地址转换函数 12.sockaddr地址结构 学习Linux的网络编程原则上基于:Linux的系统编程…...
3D沉浸式旅游网站开发案例复盘【Three.js】
Plongez dans Lyon网站终于上线了。 我们与 Danka 团队和 Nico Icecream 共同努力,打造了一个令我们特别自豪的流畅的沉浸式网站。 这个网站是专为 ONLYON Tourism 和会议而建,旨在展示里昂最具标志性的活动场所。观看简短的介绍视频后,用户…...
IO的几个模型
I/O模型名词介绍 说到I/O模型,都会牵扯到同步、异步、阻塞、非阻塞这几个词,以下讲解这几个词的概念。 阻塞和非阻塞 阻塞和非阻塞指的是一直等还是可以去做其他事。 阻塞(blocking):调用结果返回之前,…...
[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
select、poll、epoll 与 Reactor 模式
在高并发网络编程领域,高效处理大量连接和 I/O 事件是系统性能的关键。select、poll、epoll 作为 I/O 多路复用技术的代表,以及基于它们实现的 Reactor 模式,为开发者提供了强大的工具。本文将深入探讨这些技术的底层原理、优缺点。 一、I…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
ip子接口配置及删除
配置永久生效的子接口,2个IP 都可以登录你这一台服务器。重启不失效。 永久的 [应用] vi /etc/sysconfig/network-scripts/ifcfg-eth0修改文件内内容 TYPE"Ethernet" BOOTPROTO"none" NAME"eth0" DEVICE"eth0" ONBOOT&q…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
C++:多态机制详解
目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...
MySQL:分区的基本使用
目录 一、什么是分区二、有什么作用三、分类四、创建分区五、删除分区 一、什么是分区 MySQL 分区(Partitioning)是一种将单张表的数据逻辑上拆分成多个物理部分的技术。这些物理部分(分区)可以独立存储、管理和优化,…...
