Linux系统架构和开机流程解析

简介

本文主要讲解了linux系统的
一.Linux 的系统架构
从宏观上来看 Linux 系统一般分为用户态和内核态:
用户空间:指用户操作和访问的空间,这个空间常常存放我们的数据;
内核空间:使系统内核操作的一块空间,这个空间里存放系统的 内核函数和接口。当一个进程或任务调用陷入到内核代码中执行的时候,我们称之为内核态,当进程执行用户自 己的代码时,则称其处于用户态。
在这里插入图片描述

如上图所示,Linux 架构可以分为四个部分,分别是:内核、系统调用、shell 和库函数。
Linux 的内核:
Linux 的内核本质上是一种软件, 是操作系统的核心,具有很多最基本功能,它负责管理系统的进程、内存、设备驱动程序、文件和网络系统,决定着系统的性能和稳定性。
在这里插入图片描述

进程管理
当有多个任务跑到 CPU 中等待运算处理时,内核就必须要控制这些任务,让 CPU 的资源作为有效的分配。内核通过系统调用提供了一些接口对进程进行操作。

内存管理
内存管理很重要,因为系统所有的程序代码与数据都必须先存放在内存中。通常内核会 提供虚拟内存的功能,当内存不足时可以提供交换分区(swap)的功能。

设备驱动
设备驱动程序是 Linux 内核的主要部分,设备驱动程序实际控制操作系统和硬件设备之间的交互。
Shell
Shell 是系统的用户界面,提供了用户与内核进行交互操作的一种接口。它接收用户输入的命令并把它送入内核去执行,是一个命令解释器。Linux 使用的 Shell 一般是 BASH, 是 GNU 操作系统上默认的 shell。另外 Shell 也支持编程,Shell 脚本也常被用来做 Linux 系统维护。
系统调用

用户应用程序访问并使用内核所提供的各种服务的途径即是系统调用。在内核和用户应 用程序相交界的地方,内核提供了一组系统调用接口,通过这组接口,应用程序可以访问系 统硬件和各种操作系统资源。比如用户可以通过文件系统相关的系统调用,请求系统打开文 件、关闭文件或读写文件。可以通过 strace 命令查看在系统命令运行时的系统调用。
库函数
实现对函数的封装,将简单的业务逻辑接口呈现给用户,方便用户调用。read 系统调用在 C 库中的封装函数即为 read 函数
二.Linux 的开机流程
Linux 系统的开机过程是一个比较复杂的过程,但是整体上可以分为 4 个大的步骤:
按下电源按钮后 BIOS 开始工作,然后开机自检
MBR 引导
启动内核
启动第一个进程具体的启动过程分析:
BIOS/开机自检

微控制器
系统想要启动必须先要加载BIOS,BIOS 是固化到计算机主板上的一个ROM 芯片程序,是电脑启动的第一个软件。按下电源键时,会下达一条跳转指令,跳转到 BIOS 的 ROM, 使得硬件去读取主板上的 BIOS 程序。

BIOS ->POST
随后 BIOS 程序会加载 CMOS 的信息,CMOS 是一个可读写的 RAM 芯片,存储着 BIOS设置硬件参数的数据,凭借 CMOS 取得主机的硬件配置。之后 BIOS 根据这些硬件信息, 进行加电自检(Power-on self Test,POST)过程,如果 BIOS 自检阶段报错,系统就无法正常启动。
之后 BIOS 对硬件进行初始化。BIOS 将自己复制到物理内存中继续执行,接下来 BIOS 会去分析计算机中有哪些存储设备,我们以硬盘为例,BIOS 会依据用户的设置去取得能够启动的硬盘,并且到该硬盘里面去读取第一个扇区的 MBR 位置,将 MBR 加载到物理内存中执行。MBR 载入内存之后,BIOS 将控制权转交给 MBR(准确的说是 MBR 中的 Boot Loader),接下来就是 MBR 中的引导工作了。
MBR 引导(Boot Loader)
我们都知道一个磁盘中可以安装多个操作系统,这些操作系统都有自己的 loader,所以Boot Loader 只需要将控制权交给对应操作系统的 loader,让他去负责启动操作系统就行。Boot Loader 的主要功能如下:
提供选项,用户可以选择不同的启动选项,这是多重引导的重要功能。
加载内核文件,我们知道系统会有一个默认启动的操作系统,这个操作系统的 loader 在所在分区的 boot sector 中有一份,也会复制一份到 MBR 的 boot loader 中,这样一来 MBR 就会直接读取 Boot loader 中的 loader 了,也就是启动默认的操作系统。
转交其他 loader,将启动管理功能交给其他 loader 负责。
加载内核
在这里插入图片描述

加载内核文件
Boot Loader 很重要的作用就是加载内核文件,将内核文件(代码)载入到内存中执行, 内核文件就是/boot/vmlinuz,这时控制权就交给了内核,内核会重新检测各种硬件信息。我们 知道启动内核需要加载内核模块,内核模块在/lib/module 目录内,因此需要挂在根目录,这样才能读取内核模块提供的加载驱动程序功能。但是想要挂载根目录就需要相应模块的支持, 这就造成了先有鸡后又蛋的问题。

虚拟文件系统
一般实用的文件名为/boot/initrd 或者 /boot/initramfs,这个文件的特色是能够通过boot loader 来加载到内存中,然后这个文件会被解压缩并在内存中模拟成一个根目录,且此模拟在内存中的文件系统能够提供一个可执行程序,通过该程序来加载启动过程最需要的内 核模块,完成之后释放该虚拟文件系统并挂载真正的根目录。我们通过 file 指令可以看到它
是一个 gzip 压缩包,把它复制出去,修改后缀为.gz,用 gizp 命令将其加压,之后通过 file
命令查看 initramfs.img 的文件属性,最后通过 cpio 的指令解压。

在这里插入图片描述
在这里插入图片描述

我们解压之后发现内容类似于真正的根目录下的内容,这是因为它就是一个小型根目录 系统。
启动第一个进程
Systemd 执行的第一个目标就是/etc/systemd/system/default.target,它会链接到
/usr/lib/system/system/这个目录下取得 graphical.target,接下来会读取 graphical.target 的配置信息
在这里插入图片描述

我们发现在[Unit]模块中有"require=multi-user.target",这个是硬依赖,也就是说必须要启 动 multi-user.target 之后才能够 graphical.target。我们需要注意的是在/usr/lib/system/system/ 和/etc/system/system 目录下的一些.wants 目录如:graphical.target.wants 这个目录,存放的就是 graphical.target 启动时会加载的一系列服务。
我们可以以此类推,最后找到 systemd 的启动流程:
local-fs.target + swap.target:这两个 target 主要挂载本机/etc/fstab 里面所规范的文件。
sysinit.target:主要是用来检测硬件,加载所需要的内核模块等操作
basic.target:加载外围硬件驱动程序与防火墙相关任务。
multi-user.target:其他一般系统或者网络服务等
图形界面相关服务。至此,系统就启动完毕了。

三.Systemd 的分析

systemd 的介绍
Linux 上使用的最初的 init 有两个缺点:启动时间过长、启动脚本太复杂。Systemd 的出现就是为了克服 init 固有的缺点,提高系统的启动速度。

systemd 的优点是功能强大,使用方便,缺点是体系庞大,非常复杂,下图展示了
systemd 的架构

配置文件:
/usr/lib/system/system 是每个服务最主要的启动脚本设置,类似于之前的/etc/init.d
/run/system/system:系统执行过程中所产生的服务脚本,比上面的目录优先级要高
/etc/system/system: 管理员建立的执行脚本,类似于/etc/rc.d/Sxx 类的功能,比上面优先级都高。

systemd 系统管理相关命令
systemctl 是 systemd 的主命令,用于管理系统和服务。重启系统
systemctl reboot
关闭系统,切断电源systemctl poweroff CPU 停止工作systemctl halt
暂停系统
systemctl suspend
让系统进入冬眠状态
systemctl hibernate
让系统进入交互式休眠状态
systemctl hybrid-sleep
启动进入救援状态(单用户状态)
systemctl rescue
systemd-analyze 命令用于查看启动耗时。查看系统启动耗时
systemd-analyze
查看每个服务的启动耗时
systemd-analyze blame
显示瀑布状的系统启动过程流systemd-analyze critical-chain 显示指定服务的启动流
systemd-analyze critical-chain atd.service
hostnamectl 命令用于查看当前主机的信息。
显示当前主机的信息
hostnamectl
设置主机名。
hostnamectl set-hostname xuad1
localectl 命令用于查看本地化设置。查看本地化设置
localectl
设置本地化参数。
localectl set-locale LANG=zh_CN.UTF-8 localectl set-keymap zh_CN
timedatectl 命令用于查看当前系统时区设置。
查看当前时区设置
timedatectl
显示所有可用的时区timedatectl list-timezones 设置当前时区
timedatectl set-timezone Asia/Shanghai timedatectl set-time YYYY-MM-DD timedatectl set-time HH:MM:SS
loginctl 命令用于查看当前登陆的用户。列出当前 session
loginctl list-sessions 列出当前登录用户loginctl list-users
列出显示指定用户的信息
loginctl show-user root
核心概念:
Systemd 的核心概念是 unit—单元,unit 的常见类型:
service unit:这类 unit 的文件扩展名为.service,主要用于定义系统服务
target unit:这类 unit 的文件扩展名为.target,主要用于模拟实现"运行级别"的概念
device unit:这类unit 文件扩展名为.device,用于定义内核识别的设备,然后udev 利用systemd
识别的硬件,完成创建设备文件名
mount unit:这类 unit 文件扩展名为.mount,主要用于定义文件系统挂载点
socket unit:这类 unit 文件扩展名为.socket,用于标识进程间通信用到的 socket 文件
snapshot unit:这类 unit 文件扩展名为.snapshot,主要用于实现管理系统快照
swap unit:这类 unit 文件扩展名为.swap,主要用于标识管理 swap 设备
automount unit:这类 unit 文件扩展名为.automount,主要用于文件系统自动挂载设备
path unit:这类 unit 文件扩展名为.path,主要用于定义文件系统中的文件或目录

target 和运行级别:systemd 用目标(target)替代了运行级别的概念,提供了更大的灵活性, 如您可以继承一个已有的目标,并添加其它服务,来创建自己的目标。下表列举了 systemd 中的 target 和 sysvinit 中常见的 runlevel 的对应关系

Unit 相关命令
systemctl list-units 命令可以查看系统的所有 Unit 信息。列出已启动的 Unit
systemctl list-units
列出所有 Unit,包括没有找到配置文件的或者启动失败的systemctl list-units --all
列出所有没有启动的 Unit
systemctl list-units --all --state=inactive
列出所有启动失败的 Unit systemctl list-units --failed
列出所有正在运行的、类型为 service 的 Unit systemctl list-units --type=service
systemctl status 命令用于查看系统状态和单个 Unit 的状态。显示系统状态
systemctl status
显示单个 Unit 的状态
systemctl status httpd.service
显示远程主机的 nginx 服务的状态
systemctl -H root@192.168.2.204 status nginx.service
除了 status 外,systemctl 还提供了三个查询状态的简单方法,主要供脚本内部的判断语句使用。
显示某个 Unit 是否启动
systemctl is-active application.service 显示某个 Unit 是否启动失败systemctl is-failed application.service 显示某个 Unit 服务是否开机启动systemctl is-enabled application.service
systemctl 常用命令立即启动一个服务
systemctl start httpd.service 立即停止一个服务systemctl stop httpd.service 重启一个服务
systemctl restart httpd.service 杀死一个服务的所有子进程systemctl kill httpd.service
重新加载一个服务的配置文件systemctl reload httpd.service 重载所有修改过的配置文件systemctl daemon-reload
显示某个 Unit 的所有底层参数
systemctl show httpd.service
显示某个 Unit 的指定属性的值systemctl show -p CPUShares httpd.service 设置某个 Unit 的指定属性
systemctl set-property httpd.service CPUShares=500
Unit 的后缀名.service 可以省略,例如启动 ssh 的命令 systemctl start sshd.service 可以写成
systemctl start sshd。
Unit 之间存在依赖关系,A 依赖于 B,就意味着 systemd 在启动 A 的时候,同时会去启动 B。
systemctl list-dependencies 命令列出一个 Unit 的所有依赖。
systemctl list-dependencies nginx.service
上面命令的输出结果之中,有些依赖是 Target 类型,默认不会展开显示。如果要展开 Target, 就需要使用–all 参数。
systemctl list-dependencies --all nginx.service
systemctl list-unit-files 命令用于列出所有 Unit 的状态。{}列出所有 Unit 状态
systemctl list-unit-files
列出指定类型的 Unit 状态
systemctl list-unit-files --type=service
\
Unit 的四种状态enabled:开机启动disabled:不开机启动
static:该 Unit 没有[Install]部分(无法执行),只能作为其他 Unit 的依赖
masked:该 Unit 被禁止开机启动
如果修改了某个服务的配置文件,就要重新加载配置,然后重新启动,否则修改不会生效。
systemctl daemon-reload systemctl restart httpd.service 系统运行模式 target 相关命令{}查看当前系统的所有 Target
systemctl list-unit-files --type=target
查看一个 Target 包含的所有 Unit systemctl list-dependencies multi-user.target 查看启动时的默认 Target
systemctl get-default
设置启动时的默认 Target
systemctl set-default multi-user.target
\
配置文件的区块
[Unit]区块通常是配置文件的第一个区块,用来定义 Unit 的元数据,以及配置与其他 Unit
的关系。它的主要字段如下。

Description:简短描述
Documentation:文档地址
Requires:当前 Unit 依赖的其他 Unit,如果它们没有运行,当前 Unit 会启动失败
Wants:与当前 Unit 配合的其他 Unit,如果它们没有运行,当前 Unit 不会启动失败
BindsTo:与 Requires 类似,它指定的 Unit 如果退出,会导致当前 Unit 停止运行
Before:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之后启动
After:如果该字段指定的 Unit 也要启动,那么必须在当前 Unit 之前启动
Conflicts:这里指定的 Unit 不能与当前 Unit 同时运行
Condition…:当前 Unit 运行必须满足的条件,否则不会运行
Assert…:当前 Unit 运行必须满足的条件,否则会报启动失败
[Install]通常是配置文件的最后一个区块,用来定义如何启动,以及是否开机启动。它的主要字段如下。

WantedBy:它的值是一个或多个 Target,当前 Unit 激活时(enable)符号链接会放入/etc/systemd/system 目录下面以 Target 名 + .wants 后缀构成的子目录中
RequiredBy:它的值是一个或多个 Target,当前 Unit 激活时,符号链接会放入
/etc/systemd/system 目录下面以 Target 名 + .required 后缀构成的子目录中

Alias:当前 Unit 可用于启动的别名
Also:当前 Unit 激活(enable)时,会被同时激活的其他 Unit
[Service]区块用来 Service 的配置,只有 Service 类型的 Unit 才有这个区块。它的主要字段如下。

Type:定义启动时的进程行为。它有以下几种值。
Type=simple:默认值,执行 ExecStart 指定的命令,启动主进程
Type=forking:以 fork 方式从父进程创建子进程,创建后父进程会立即退出
Type=oneshot:一次性进程,Systemd 会等当前服务退出,再继续往下执行
Type=dbus:当前服务通过 D-Bus 启动
Type=notify:当前服务启动完毕,会通知 Systemd,再继续往下执行
Type=idle:若有其他任务执行完毕,当前服务才会运行
ExecStart:启动当前服务的命令
ExecStartPre:启动当前服务之前执行的命令
ExecStartPost:启动当前服务之后执行的命令
ExecReload:重启当前服务时执行的命令
ExecStop:停止当前服务时执行的命令
ExecStopPost:停止当其服务之后执行的命令

RestartSec:自动重启当前服务间隔的秒数
Restart:定义何种情况 Systemd 会自动重启当前服务,可能的值包括 always(总是重启)、on-success、on-failure、on-abnormal、on-abort、on-watchdog
TimeoutSec:定义 Systemd 停止当前服务之前等待的秒数
Environment:指定环境变量

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值