当前位置: 首页 > Linux

干货分享——Systemd技术原理与实践(下)

时间:2023-04-06 02:28:06 Linux

systemd是文章的续篇。上一期我们介绍了systemd的基本概念。本期我们将详细讲解systemd的运行逻辑,希望能优化研究系统的资源。优客的。systemd时代的引导过程在systemd作为系统的init程序的时代,Linux系统的引导过程大致可以分为六个阶段:BIOS自检阶段、GRUB引导阶段、kernel内核加载阶段、initrd虚拟根文件系统阶段,systemd初始化阶段,终端登录阶段。每个阶段各司其职,为下一阶段铺路。它们相互关联,缺一不可。下面分别介绍一下各个阶段:1.BIOS自检阶段。当我们启动电脑,按下电源键,电脑开始开机,然后系统开始加载主板内存中的第一段代码:BIOS,系统进入BIOS。自测阶段。BIOS是基本输入输出系统,全称是BasicInputOutputSystem,烧录在主板的内存上,里面的内容只能读取不能更改,如果要更改,可以只能重新烧录到主板内存中了。BIOS在开机阶段最重要的功能就是开机自检,对连接在主板上的硬件设备一一进行检查,如检查CPU、主板、内存、软盘系统、键盘、光驱等已连接。正常,不管有没有故障。当一些主要硬件(如CPU、内存等)出现问题时,BIOS会报错,无法继续启动系统。我们在开机时听到的哔哔声就是BIOS蜂鸣器发出的声音。当硬件出现问题时,可以听到蜂鸣器响两三声报错,系统无法启动下一步。.BIOS检查所有硬件状态,状态无误后,会按照设定的启动顺序找到相应的启动盘,然后引导系统进入相应的启动盘继续启动系统。有刷机经验的朋友应该都知道,在系统启动时,按F12或delete键进入BIOS界面,然后选择对应的启动盘进行刷机。启动盘可以是安装好的U盘、光驱,也可以BIOS设置默认启动顺序,比如可以设置U盘为第一启动项,BIOS会引导系统找到对应的启动项U盘启动时的硬件界面,BIOS会继续尝试第二启动项。选择启动项后,系统进入对应的启动盘,开始执行启动盘中第一个磁盘第一个扇区的代码。至此,BIOS自检阶段结束。.2、GRUB引导阶段GRUB是GRandUnifiedBootloader的缩写,它是一个多操作系统的管理器,存放在第一个磁盘第一个扇区的主引导扇区,如果你的电脑系统比较多,比如Linux系统和Windows系统,这时可以使用GRUB移动光标选择你要进入的系统。选择系统后,GRUB会根据系统分区表找到系统对应的磁盘分区,并加载对应的grub.cfg配置文件,通过配置文件,加载/boot分区的文件系统驱动,然后在文件系统中找到系统内核,将内核加载进去并启动,最后将系统的控制权交给内核,GRUB引导阶段结束。除了引导系统的主要功能外,GRUB还可以通过grub.cfg配置文件实现一些其他功能。grub.cfg配置文件存放在/boot/grub/目录中。在配置文件中,linux参数表示系统启动时加载的内核。当系统中存储了多个内核,或者在您的计算机上修改编译了一个新的内核时,您可以配置此项来选择相应的内核进行加载;quiet参数类似于loglevel参数,用于配置日志启动的级别;splash参数用于配置相应的启动动画等。3、Kernel内核加载阶段在讲解内核的启动之前,我们先简单介绍一下Linux内核。Linux内核是一个宏内核,是运行在单一地址空间的单个程序,它集成了系统的一些基本功能,如进程线程管理、内存管理、文件系统、驱动程序管理、网络管理等。内核中的每个函数都可以访问其内核的其他部分。与微内核(代表:Windows系统)不同,微内核将这些功能独立划分为不同的服务,服务通过通信接口与中央内核进行通信。GRUB引导阶段结束时,内核接管系统后,首先开始初始化系统中各种设备的配置,包括CPU、I/O设备、存储设备等的初始化,其次,内核创建内核态kernel_init进程,然后找到initrd文件并解压,在initrd虚拟根文件系统中加载驱动完成相关硬件的初始化,最后调用initrd虚拟根的init脚本文件系统,至此,内核在系统启动过程中的作用基本已经完成,内核开始等待initrd执行init进程,内核加载阶段结束。4.initrd虚拟根文件系统阶段initrd(InitialRAMDisk)是一个虚拟根文件系统,在GRUB阶段复制到内存中,在内核中解压。它是一个临时的虚拟根文件系统,解压后可以看到它的目录结构和实际的根文件系统差不多,里面包含了一些驱动。下图为解压后的Kylininitrd下虚拟根文件系统的目录结构。精简,只保留最基本的模块,所以没有各种设备硬件的驱动。这些驱动程序存储在initrd中。内核启动时,从initrd中加载必要的驱动模块,完成硬件的初始化,然后,内核开始执行虚拟根文件系统中的init程序,即虚拟根文件系统下的systemd程序。通过上面的描述,可以总结出虚拟根文件系统的阶段大致可以分为两个过程:内核加载initrd中的驱动,虚拟根文件系统下的systemd程序加载这两个过程。因此,虚拟根文件系统也可以将系统阶段分为内核加载阶段和systemd初始化阶段,是与上下阶段重叠的阶段。此外,initrd还提供了启动图形界面美化功能,用于覆盖系统启动时的日志输出,提高用户体验。当initrd下的systemd进程完成环境的初始化,系统切换到真正的根文件系统时,initrd阶段结束。5、systemd初始化阶段systemd是systemdeamon的缩写,是Linux系统基本组件的集合,提供系统和服务的管理,是pid为1的init进程,是所有进程的父进程过程。需要进一步了解systemd进程的朋友可以阅读上一篇文章:systemd介绍,这里重点讲解systemd在启动过程中做了哪些事情。通过前面的描述,我们可以将systemd分为两个阶段:虚拟根文件系统阶段和真实根文件系统阶段。内核通过解压initrd文件得到虚拟根文件系统,然后在虚拟根文件系统下执行init程序启动systemd,systemd作为内核的子进程开始运行在虚拟根文件系统下。虚拟根文件下的systemd首先检查当前系统,比如判断系统是运行在用户态还是系统态,系统是处于正常启动状态还是异常错误后的重启状态等,然后进行一些系统初始化配置,包括:环境变量的配置、日志的相关配置等,然后挂载一些关键文件系统,主要包括/proc、/sys、/dev、/var等基本文件系统目录。这一步之后,systemd开始准备切换真正的根文件目录,保存一些配置项,进行一些环境适配,systemd脱离内核控制执行setsid()系统调用,成为一个完全独立的父进程,至此systemdsystemd的虚拟根文件系统阶段结束,systemd进入真正的根文件系统阶段。在真正的根文件系统阶段,systemd在切换后首先进行一些环境适配,然后开启日志终端功能,将系统启动时临时保存在内核中的日志提取出来,整理后存储到相应的日志文件中。接下来systemd开始获取一些系统能力和系统相关的初始化配置,比如:CPU亲和性获取、主机名配置、系统ID配置、cgroup控制器挂载、loopback网络配置等,完成之后以上初始化工作,systemd作为一个PID为1的守护进程,开始创建和管理各个系统服务,根据对应的Unit配置单元文件执行相应的系统服务,通过各个服务逐步完成系统启动工作。systemd执行Unit的顺序大致可以分为sysinit.target->basic.target->default.target,其中sysinit.target和basic.target主要用来启动一些与系统初始化相关的服务,执行一些早期的启动任务。task,default.target指向不同的“运行级别”target文件,如果进入命令行模式,则指向multi-user.target文件,如果进入图形界面模式,则指向graphical.target文件。至此,systemd启动阶段的工作就完成了。6、终端登录阶段systemd初始化阶段完成后,系统根据配置的操作级别进入不同的登录界面。下面主要从图形化登录界面进行介绍。在优麒麟操作系统中,systemd后的启动流程主要是:systemd->lightdm->Xorg->lightdm-greeter->ukui-greeter->ukui-session,通过pstree命令可以看到如下内容优麒麟终端两个进程树:lightdm是一个新的,轻量级的Linux桌面显示管理器,它会先拉起Xorg,Xorg是负责绘制屏幕的显示后台,然后lightdm也会拉起lightdm-greeter,lightdm-greeter是lightdm的子进程,它会拉起ukui-greeter进程,ukui-greeter是登录界面进程,所以当ukui-greeter启动后,系统进入登录界面,输入登录用户名和密码,用户名和密码验证通过后,lightdm创建一个个人的ukui-session桌面窗口管理器进程。至此,终端登录阶段结束,系统启动。systemd相关命令systemd提供了systemctl相关命令用于管理系统,下面介绍一些基本的常用命令:1.系统管理命令,控制系统电源状态重启系统$sudosystemctlreboot关闭系统,切断电源$sudosystemctlpoweroff暂停系统使系统进入休眠状态$sudosystemctlsuspend使系统进入休眠状态$sudosystemctlhibernate让系统进入交互式休眠状态$sudosystemctlhybrid-sleep2.systemd-analyze命令,用于查看启动时间,可用于分析系统启动效率查看启动时间$systemd-analyze查看各个服务的启动时间$systemd-analyzeblame显示瀑布式启动流程$systemd-analyzecritical-chain显示指定服务的启动流程$systemd-analyzecritical-chainatd.service3.hostnamectl命令,用于查看当前主机信息显示当前主机信息$hostnamectl设置主机名$sudohostnamectlset-hostnamerhel74.Unit相关命令,用于管理Unit配置单元列出正在运行的单元$systemctllist-units列出所有单元,包括那些没有找到配置文件或启动失败的单元$systemctllist-units--all列出所有没有运行的单元$systemctllist-units--all--state=inactive列出所有加载失败的单元$systemctllist-units--failed列出所有正在运行的服务类型单元$systemctllist-units--type=service立即启动服务$sudosystemctlstartapache.service立即停止服务$sudosystemctlstopapache.service重新启动服务$sudosystemctlrestartapache.servicekill一个服务的所有子进程$sudosystemctlkillapache.service重新加载一个服务的配置文件$sudosystemctlreloadapache.service重新加载所有修改过的配置文件$sudosystemctldaemon-reload显示一个Unit的所有底层参数$systemctlshowhttpd.service显示Unit$systemctlshow-pCPUShares的指定属性值httpd.service设置Unit$sudosystemctlset-propertyhttpd.serviceCPUShares=5005的指定属性。日志管理,使用查看过滤系统日志查看所有日志(默认只保存本次启动的日志)$sudojournalctl查看内核日志(不显示应用日志)$sudojournalctl-k查看本次系统启动日志$sudojournalctl-b$sudojournalctl-b-0查看上次启动的日志(需要更改设置)$sudojournalctl-b-1查看指定时间的日志$sudojournalctl--since="2012-10-3018:17:16"$sudojournalctl--since"20分钟前"$sudojournalctl--sinceyesterday$sudojournalctl--since"2015-01-10"--until"2015-01-1103:00"$sudojournalctl--since09:00--until"1hourago"显示最后10行日志$sudojournalctl-n显示指定行数的日志最后$sudojournalctl-n20滚动显示实时最新的日志$sudojournalctl-f查看指定服务的日志$sudojournalctl/usr/lib/systemd/systemd查看指定进程的日志$sudojournalctl_PID=1查看某个路径下某个脚本的日志$sudojournalctl/usr/bin/bash查看指定用户的日志$sudojournalctl_UID=33--sincetoday查看某个Unit的日志$sudojournalctl-unginx.service$sudojournalctl-unginx.service--sincetoday实时滚动显示某个Unit的最新日志$sudojournalctl-unginx.service-f查看指定优先级(及以上)的日志,共8级0:emerg1:alert2:crit3:err4:warning5:notice6:info7:debug$sudojournalctl-perr-b日志默认分页输出,--no-pager改为正常标准输出$sudojournalctl--no-pager显示日志占用的硬盘空间log$sudojournalctl--disk-usage指定日志文件占用的最大空间$sudojournalctl--vacuum-size=1G指定日志文件保存多长时间$sudojournalctl--vacuum-time=1years