Linux基礎命令介紹十三:啟動流程
固件(firmware)是指設備***層的,讓設備得以運行的程序代碼。簡單理解就是:固定在硬件上的軟件。計算機中的許多設備都擁有固件(如硬盤、鼠標、光驅、U盤等),在計算機啟動過程中,***讀取的就是位于主板上的固件,這個固件當前有兩種類型:傳統的BIOS和新的通用性更強的UEFI。
在上一篇中,我們提到另一種磁盤分區格式GTP也是UEFI標準的一部分。于是,當前計算機啟動中,出現了兩種不同的方式:BIOS/MBR和UEFI/GTP。
在linux操作系統的世界中,同樣在經歷著變革,系統初始化軟件sysvinit正逐漸被systemd取代。
本文將主要講述傳統的BIOS/MBR-->sysvinit啟動方式,同時,作為補充,也將簡述UEFI/GTP-->systemd的啟動方式。
BIOS/MBR-->sysvinit
1、BIOS階段
系統加電后會立即讀取BIOS中內容并執行,BIOS中程序的執行包括兩個步驟:
1)加電自檢POST(power-on self test),主要負責檢測系統外圍設備(如CPU、內存、顯卡、鍵盤鼠標等)是否正常。如果硬件出現問題,主板會發出不同含義的蜂鳴聲,啟動終止。如果沒有問題,屏幕就會顯示出CPU、內存、硬盤等信息。
2)自檢完成后,BIOS會執行一段程序來枚舉本地設備(如光盤、U盤、硬盤、網絡等,可以在BIOS中設置枚舉順序)尋找下一階段的啟動程序所在位置。BIOS會將控制權交給啟動順序(Boot Sequence)中排在***位的設備,此時,計算機讀取該設備中的最前面的512個字節,如果這512個字節的***兩個字節是0x55和0xAA(Magic Number),表明這個設備可以用于啟動;如果不是,表明該設備不能用于啟動,控制權于是轉交給啟動順序中的下一個設備。如上一篇所述,硬盤中的最前面的512字節即為主引導記錄 MBR。
2、MBR階段
前一篇中我們描述過MBR的結構,其中包括446字節的Bootloader,64字節的DPT和2字節的Magic Number。
Bootloader(引導加載程序)中較常用的一種是grub,grub引導分為兩個階段(有些grub還定義了1.5階段):
1)BIOS將stage1載入內存中的指定位置(0x7C00)并跳轉執行,stage1的內容即為MBR中起始的446字節;此階段執行作用主要是將硬盤0磁頭0磁道2扇區的內容載入到內存0x8000處并跳轉執行。
1.5)由于stage2的代碼(較大)存放在文件系統下的/boot分區中(或者/boot沒有單獨分區的/etc/),因此識別stage2文件需要文件系統環境(此時還只能直接讀取硬盤指定位置的內容,并不能識別文件系統)。stage1.5的作用就是為stage2提供文件系統環境,使系統能夠找到位于文件系統中的stage2文件。
2)stage2被載入內存并執行,它首先會解析grub的配置文件menu.lst即/boot/grub/grub.conf,該文件中指定了系統內核文件所處的位置,如果沒有找到該文件,就會執行一個shell,等待用戶手動指定內核文件的位置。此階段的最終狀態就是執行boot命令,將內核和initrd鏡像載入內存,進而將控制權交給內核。
grub.conf內容(版本:GNU GRUB 0.97):
- # grub.conf generated by anaconda
- #
- # Note that you do not have to rerun grub after making changes to this file
- # NOTICE: You have a /boot partition. This means that
- # all kernel and initrd paths are relative to /boot/, eg.
- # root (hd0,0)
- # kernel /vmlinuz-version ro root=/dev/sda3
- # initrd /initrd-version.img
- #boot=/dev/sda
- default=0
- timeout=5
- splashimage=(hd0,0)/grub/splash.xpm.gz
- hiddenmenu
- title CentOS (2.6.18-407.el5)
- root (hd0,0)
- kernel /vmlinuz-2.6.18-407.el5 ro root=LABEL=/ rhgb quiet
- initrd /initrd-2.6.18-407.el5.img
- title CentOS (2.6.18-398.el5)
- root (hd0,0)
- kernel /vmlinuz-2.6.18-398.el5 ro root=LABEL=/ rhgb quiet
- initrd /initrd-2.6.18-398.el5.img
文件中#開頭的行是注釋行,最重要的部分是兩個title下面指定的內核位置及具體文件(kernel和initrd項)
3、內核階段
grub的stage2將initrd文件加載到內存中,內核于是開始執行initrd中的init文件,此文件是一個腳本,主要作用是加載各種存儲介質相關的設備驅動程序。當所需的驅動程序加載完成后,會創建一個根設備,然后將根文件系統(rootfs)以只讀的方式掛載。這一步結束后,釋放未使用的內存,轉換到真正的根文件系統中運行程序/sbin/init,啟動系統PID為1的進程。此后系統的控制權就交給/sbin/init進程了。
4、init階段
當init進程接管了系統的控制權之后,它首先會讀取/etc/inittab文件,此文件描述了在特定的運行級別(runlevel)下,init進程該如何初始化系統。
- linux中定義了7種運行級別:
- 0 表示關機
- 1 表示單用戶模式
- 2 表示無網絡的多用戶模式
- 3 表示多用戶模式
- 4 未使用
- 5 表示圖形界面模式
- 6 表示重啟
inittab文件中指定了系統的默認運行級別,如id:3:initdefault:表示默認運行級別為3(多用戶模式)。
init進程根據inittab文件,運行一系列指定的初始化腳本:
1)/etc/rc.d/rc.sysinit系統初始化腳本,它的作用包括設置主機名和默認網關、決定是否啟用SELinux、加載用戶自定義模塊、根據文件/etc/sysctl.conf設置內核參數、設置raid及LVM等硬盤功能、重新以讀寫方式掛載根文件系統等等
2)執行/etc/rc.d/rc文件,該文件確認由inittab指定的運行級別N,并啟動相應級別下的服務(通過執行/etc/rc.d/rcN.d中的文件),例如運行級別為3時,則先執行/etc/rc.d/rc3.d下以K開頭的文件,然后執行以S開頭的文件。這些文件都是指向/etc/init.d下的符號鏈接。以K開頭的文件表示此運行級別下需要關閉的服務,以S開頭的文件表示此運行級別下需要開啟的服務。
3)在運行級別2、3、4、5中***一個執行的文件均指向文件/etc/rc.local,用戶可以在此文件中自定義啟動內容。
4)之后根據inittab中設置,運行6個終端,以便用戶登錄系統,如果是運行級別5,則還會執行/etc/X11/prefdm -nodaemon啟動相應的桌面環境。
5)然后執行/bin/login程序用于接收和驗證來自mingetty的用戶名和密碼。
至此整個系統即啟動完畢了
UEFI/GTP-->systemd
UEFI的出現是為了代替BIOS,同樣,GTP和systemd也是為了彌補MBR和sysvinit的不足。和BIOS只負責POST和找到MBR不同,UEFI將貫穿系統加電到關機的整個過程。粗略劃分,UEFI系統啟動分為4個階段:
1、UEFI初始化階段
1)SEC(安全驗證):接收并處理系統啟動和重啟信號,初始化臨時存儲區域,傳遞系統參數給下一階段(即PEI)。
2)PEI(EFI前期初始化):為DXE準備執行環境,將需要傳遞到DXE的信息組成HOB(Handoff Block)列表,最終將控制權轉交到DXE手中。
3)DXE(驅動執行環境):根據HOB列表初始化系統服務,然后遍歷固件中的所有Driver,當驅動的依賴資源滿足時,調度Dirver到執行隊列執行,直到所有滿足條件的Dirver都被加載。
2、操作系統加載器作為UEFI應用程序運行階段
1)BDS(啟動設備選擇):初始化控制臺設備,加載必要的設備驅動,根據系統設置加載和執行啟動項,用戶選中某個啟動項(或系統進入默認的啟動項)后,OS Loader啟動,系統進入TSL階段。
UEFI中程序能夠識別存儲介質上的分區信息和文件系統(如:fat32),此時會將/EFI/boot/grub2.efi(位于GTP格式硬盤的一個分區ESP,安裝時自動生成)作為UEFI應用程序運行。
2)TSL(臨時系統加載):操作系統加載器(OS Loader也位于ESP分區)執行的***階段,在這一階段OS Loader作為一個UEFI應用程序運行,系統資源仍然由UEFI內核控制。當啟動服務的ExitBootServices()服務被調用后,系統進入RT(Run Time)階段。
3、操作系統運行階段
RT(運行時):系統的控制權從UEFI內核轉交到OS Loader手中,UEFI占用的各種資源被回收到OS Loader,僅有UEFI運行時服務保留給OS Loader和OS使用。隨著OS Loader的執行,OS最終取得對系統的控制權。
在init作為系統初始化程序時,服務是通過/etc/rc.d/init.d中的腳本來管理并且是順序執行的,當使用systemd作為系統初始化程序后,這些腳本被服務單元替換,并盡可能的并行啟動進程。
在systemd中,一個單元配置文件可以描述如下內容之一:
- 系統服務(.service)
- 掛載點(.mount)
- 套接字(.sockets)
- 系統設備(.device)
- 交換分區(.swap)
- 文件路徑(.path)
- 啟動目標(.target)
- 由systemd管理的計時器(.timer)
- ....
systemd為保持向下兼容性還保留了一些init命令和概念,但所對應的文件都是指向systemd對應命令或文件的符號鏈接:
- [root@centos7 temp]# ls -l /sbin/init
- lrwxrwxrwx. 1 root root 22 1月 15 2016 /sbin/init -> ../lib/systemd/systemd
- [root@centos7 temp]# ls -l /usr/lib/systemd/system/runlevel*.target
- lrwxrwxrwx. 1 root root 15 1月 15 2016 /usr/lib/systemd/system/runlevel0.target -> poweroff.target
- lrwxrwxrwx. 1 root root 13 1月 15 2016 /usr/lib/systemd/system/runlevel1.target -> rescue.target
- lrwxrwxrwx. 1 root root 17 1月 15 2016 /usr/lib/systemd/system/runlevel2.target -> multi-user.target
- lrwxrwxrwx. 1 root root 17 1月 15 2016 /usr/lib/systemd/system/runlevel3.target -> multi-user.target
- lrwxrwxrwx. 1 root root 17 1月 15 2016 /usr/lib/systemd/system/runlevel4.target -> multi-user.target
- lrwxrwxrwx. 1 root root 16 1月 15 2016 /usr/lib/systemd/system/runlevel5.target -> graphical.target
- lrwxrwxrwx. 1 root root 13 1月 15 2016 /usr/lib/systemd/system/runlevel6.target -> reboot.target
systemd啟動后執行的***個目標是default.target,但實際上default.target是指向graphical.target的符號鏈接。
- [root@centos7 temp]# ls -l /usr/lib/systemd/system/default.target
- lrwxrwxrwx. 1 root root 16 1月 15 2016 /usr/lib/systemd/system/default.target -> graphical.target
- [root@centos7 temp]# cat /usr/lib/systemd/system/graphical.target
- # This file is part of systemd.
- #
- # systemd is free software; you can redistribute it and/or modify it
- # under the terms of the GNU Lesser General Public License as published by
- # the Free Software Foundation; either version 2.1 of the License, or
- # (at your option) any later version.
- [Unit]
- Description=Graphical Interface
- Documentation=man:systemd.special(7)
- Requires=multi-user.target
- Wants=display-manager.service
- Conflicts=rescue.service rescue.target
- After=multi-user.target rescue.service rescue.target display-manager.service
- AllowIsolate=yes
其中Requires行指明了本單元的依賴關系(其他各項意義可以通過命令man systemd.unit查看),順著此文件,可以找到需要執行的單元:multi-user.target、basic.target、sysinit.target、local-fs.target swap.target、local-fs-pre.target。
4、關機階段
AL(After-life):當系統硬件或操作系統出現嚴重錯誤不能繼續正常運行時,固件會嘗試修復錯誤,這時系統進入AL期。UEFI標準并沒有定義此階段的行為和規范。系統供應商可以自行定義。
相關命令
init
1、init
init除了在系統初始化時起的重要作用外,還可以用來執行關機、重啟、切換運行級別的作用:
- #關機
- init 0
- #重啟
- init 6
- #切換到單用戶模式
- init 1
2、runlevel 顯示運行級別
- [root@centos7 temp]# runlevel
- N 3
- [root@centos7 temp]#
輸出中N表示當前運行級別,如果系統啟動后切換過運行級別,則輸出類似于3 5表示之前運行級別為3,現在的運行級別為5。
3、halt reboot poweroff shutdown
- #立即關機
- shutdown -h now
- #在11:50分執行關機
- shutdown -h 11:50
- #如果要取消指定時間的關機,則在另一個終端中執行:
- shutdown -c
- #過30分鐘之后重啟系統,并且重啟時不進行磁盤檢測
- shutdown -fr +30
4、chkconfig 更新或查詢服務的運行級別信息
- #列出服務(還會列出xinetd管理的服務)
- chkconfig --list
- #增加一個服務
- chkconfig --add httpd
- #使服務在運行級別2、3、5時自啟動
- chkconfig --level 235 httpd on
5、service 運行服務腳本(服務腳本位于/etc/init.d內,service本身也是腳本,位于/sbin內)
- #列出所有服務狀態
- service --status-all
- #列出單個服務狀態
- service nginx status
- #啟動服務
- service nginx start
- #停止服務
- service nginx stop
- #重啟服務
- service nginx restart
- #重新加載配置文件
- service nginx reload
systemd
systemd并不是一個命令,而是一組命令,涉及到系統管理的方方面面。
1、systemctl 控制systemd系統和管理服務
- systemctl [OPTIONS...] COMMAND [NAME...]
如切換運行級別或開關機:
- #重啟(將執行reboot.target)
- systemctl reboot
- #暫停(將執行suspend.target)
- systemctl suspend
- #休眠(將執行hibernate.target)
- systemctl hibernate
- #切換至救援模式(單用戶,將執行rescue.target)
- systemctl rescue
- #列出運行級別
- systemctl get-default
- #切換到運行級別5,即圖形模式
- systemctl isolate graphical.target
系統服務單元相關:
- #列出正在運行的 Unit
- systemctl list-units
- #列出所有的 Unit
- systemctl list-units --all
- #列出所有加載失敗的 Unit
- systemctl list-units --failed
- #列出Unit時指定類型
- systemctl list-units --type=socket
系統和服務管理:
- #系統狀態
- systemctl status
- #服務狀態(.service可以省略)
- systemctl status nginx.service
- #啟動服務
- systemctl start nginx
- #停止服務
- systemctl stop nginx
- #重啟服務
- systemctl restart nginx
- #重新加載配置文件
- systemctl reload nginx
- #設置服務開機啟動
- systemctl enable nginx
- #列出所有安裝的服務
- systemctl list-unit-files
- #指定類型
- systemctl list-unit-files --type=target
還有許多其他選項,這里就不一一列舉了。
2、systemd-analyze 查看啟動用時
- [root@centos7 ~]# systemd-analyze
- Startup finished in 730ms (kernel) + 1.904s (initrd) + 9.909s (userspace) = 12.544s
輸出顯示了系統啟動過程中各部分耗時
- #各服務初始化用時
- [root@centos7 ~]# systemd-analyze blame
- 5.424s NetworkManager-wait-online.service
- 1.830s dev-mapper-centos\x2droot.device
- 1.055s firewalld.service
- 980ms kdump.service
- 549ms network.service
- ....
- #輸出各服務用時細節并寫入文件(該文件可以用瀏覽器或圖片查看器打開)
- [root@centos7 ~]# systemd-analyze plot > file.svg
- #序列化輸出各服務詳細完整的狀態信息(輸出內容很多,略)
- [root@centos7 ~]# systemd-analyze dump
3、systemd-cgls 遞歸顯示控制組(Cgroups)信息
linux內核從版本2.6.24開始,引入了一個叫做控制組(control groups)的特性,是用于限制、記錄、隔離進程組(process groups)所使用的物理資源(如:cpu,memory,IO等等)的機制。關于Cgroups的內容本文不再展開。
- [root@centos7 ~]# systemd-cgls
- ├─1 /usr/lib/systemd/systemd --switched-root --system --deserialize 21
- ├─user.slice
- │ └─user-0.slice
- │ ├─session-182.scope
- │ │ ├─5165 sshd: root@pts/1
- │ │ ├─5167 -bash
- │ │ ├─5409 systemd-cgls
- ....
- ....
4、systemd-cgtop 顯示各控制組的使用量(CPU,內存,IO)
顯示效果類似命令top
- [root@centos7 ~]# systemd-cgtop
- Path Tasks %CPU Memory Input/s Output/s
- / 161 0.2 400.5M - -
- /system.slice/NetworkManager.service 1 - - - -
- /system.slice/auditd.service 1 - - - -
- /system.slice/crond.service 1 - - - -
- /system.slice/dbus.service 1 - - - -
- /system.slice/firewalld.service 1 - - - -
- ....
5、systemd-loginctl 控制systemd登錄管理
此命令是命令loginctl的符號鏈接
- #列出當前會話
- [root@centos7 ~]# systemd-loginctl list-sessions
- SESSION UID USER SEAT
- 182 0 root
- 154 0 root
- 2 sessions listed.
- #列出當前登錄用戶
- [root@centos7 ~]# loginctl list-users
- UID USER
- 0 root
- 1 users listed.
- #列出顯示指定用戶的信息
- [root@centos7 ~]# loginctl show-user root
- UID=0
- GID=0
- Name=root
- Timestamp=三 2016-12-21 08:38:54 CST
- TimestampMonotonic=77015538361
- RuntimePath=/run/user/0
- Slice=user-0.slice
- Display=154
- State=active
- Sessions=182 154
- IdleHint=no
- IdleSinceHint=0
- IdleSinceHintMonotonic=0
- Linger=no
- [root@centos7 ~]#
6、timedatectl 系統時間和日期控制
- [root@centos7 ~]# timedatectl
- Local time: 三 2016-12-21 13:47:31 CST
- Universal time: 三 2016-12-21 05:47:31 UTC
- RTC time: 三 2016-12-21 05:47:31
- Time zone: Asia/Shanghai (CST, +0800)
- NTP enabled: n/a
- NTP synchronized: no
- RTC in local TZ: no
- DST active: n/a
- #設置時間
- [root@centos7 ~]# timedatectl set-time "2012-10-30 18:17:16"
- #列出時區
- [root@centos7 ~]# timedatectl list-timezones
- Africa/Abidjan
- Africa/Accra
- Africa/Addis_Ababa
- Africa/Algiers
- Africa/Asmara
- ....
- #設置時區
- [root@centos7 ~]# timedatectl set-timezone America/New_York
7、hostnamectl 系統主機名控制
- #狀態
- [root@centos7 ~]# hostnamectl status
- Static hostname: centos7
- Icon name: computer-vm
- Chassis: vm
- Machine ID: 956ab824a02d489d85b079cb442d5442
- Boot ID: 9016d7627d8148ecb7fb77afaa89aeab
- Virtualization: vmware
- Operating System: CentOS Linux 7 (Core)
- CPE OS Name: cpe:/o:centos:centos:7
- Kernel: Linux 3.10.0-327.el7.x86_64
- Architecture: x86-64
- #設置主機名(內核參數/proc/sys/kernel/hostname和文件/etc/hostname中都立即更新)
- [root@centos7 ~]# hostnamectl set-hostname MYHOST
- #重新登錄后主機名即變為myhost(靜態主機名)
- [root@centos7 ~]# hostnamectl
- Static hostname: myhost
- Pretty hostname: MYHOST
- Icon name: computer-vm
- Chassis: vm
- Machine ID: 956ab824a02d489d85b079cb442d5442
- Boot ID: 9016d7627d8148ecb7fb77afaa89aeab
- Virtualization: vmware
- Operating System: CentOS Linux 7 (Core)
- CPE OS Name: cpe:/o:centos:centos:7
- Kernel: Linux 3.10.0-327.el7.x86_64
- Architecture: x86-64
以上systemd相關所有命令(除systemd-cgls和systemd-cgtop外),都可以使用選項-H指定遠程基于systemd的主機(使用ssh協議):
- [root@centos7 ~]# hostnamectl -H 10.0.1.252
- Static hostname: idc-v-71252
- Icon name: computer-vm
- Chassis: vm
- Machine ID: 956ab824a02d489d85b079cb442d5442
- Boot ID: 9016d7627d8148ecb7fb77afaa89aeab
- Virtualization: vmware
- Operating System: CentOS Linux 7 (Core)
- CPE OS Name: cpe:/o:centos:centos:7
- Kernel: Linux 4.4.4-1.el7.elrepo.x86_64
- Architecture: x86-64
systemd功能強大,使用方便,但也比較復雜,體系龐大。本文只介紹一點相關命令,更多內容就不在此展開了。
本文簡述了傳統的BIOS和新的UEFI啟動流程,介紹了init和systemd部分相關命令。