uboot启动流程概述_Alibaba Cloud Linux 2 LTS OS 启动优化实践
Alibaba Cloud Linux 2 (原Aliyun Linux 2)是阿里云操作系統團隊基于社區版 4.19 LTS 內核打造的一款針對云產品優化的下一代 Linux 操作系統發行版,不僅提供 Linux 社區的最新增強功能,也提供了云上最佳用戶體驗并針對阿里云基礎設施做了深度的優化。今年 3 月 26 日Alibaba Cloud Linux 2 LTS 正式發布,這是一個重要的里程碑。在 LTS 版本中,阿里云操作系統團隊將提供長期的技術支持、穩定的安全更新以及持續的特性與優化。
阿里云同時推出了基于 Alibaba Cloud Linux 2 LTS 的快速啟動版鏡像,當前正在火熱公測中,用戶可以在北京、杭州、張家口、香港等可用區的控制臺中購買試用。Alibaba Cloud Linux 2 LTS 為快速啟動版做了大量優化工作,本文將深度披露相關操作系統側的優化技術細節。
鏡像目前在北京、杭州、張家口、香港等可用區公測,歡迎購買試用。
1、Linux 系統啟動流程簡介
我們首先需要定義 Linux 系統啟動,這里我們定義為從系統上電到用戶能夠登錄終端的時間為啟動時長,對于云上用戶來說,從 Guest OS 啟動到用戶可以通過 ssh 登錄的階段,為系統啟動階段。通用 Linux 操作系統啟動大致分為三個階段:引導階段(第一階段),內核啟動階段(第二階段)及用戶態啟動階段(第三階段),相關流程如下圖所示:
下面來看看各階段大致的啟動流程。
第一階段
Bootloader 是位于系統引導扇區的一段獨立的系統程序,用于系統啟動初期的硬件初始化,系統分區識別,系統內核加載及跳轉執行。目前應用比較廣泛的 bootloader 是用于通用系統的 Grub2 和嵌入式系統的 uboot。Grub2 是多重引導器(multiboot),提供交互界面,默認配置下 Grub2 有5秒交互超時時間,啟動耗時較長。
第二階段
Bootloader 加載 Linux 內核(一般為壓縮內核 vmlinuz)到內存,并運行內核自解壓縮程序,解壓后跳轉至start_kernel(),開始內核初始化流程:
第三階段
Linux 內核完成一系列初始化動作之后,開始運行 init 程序,創建 PID 為 1 的用戶態進程,將系統控制權從內核態跳轉到用戶態。init 程序會繼續進行用戶態啟動流程,開啟各種必要的或是預先配置的系統服務,最后啟動登陸服務,完成整個系統的啟動。
Initrd 與 Switch Root
init 是用戶態程序,存放在系統根文件系統(rootfs)里。內核需要先掛載 rootfs,才能運行 init 程序。通用 Linux 發行版需要支持多種磁盤設備及文件系統,這需要內核預加載多種可能的磁盤設備驅動及文件系統相關用戶態工具軟件才能正確識別 rootfs。而這些驅動及用戶態工具一般都存放在 rootfs 中,形成一個循環依賴。
為解決這個問題,initrd 應運而生,將掛載 rootfs 必要的驅動、用戶態工具以及其他需要預加載的代碼從 rootfs 中抽取出來,并依照 rootfs 的文件結構,打包成一個小的 rootfs,做成一個內存盤(ram disk)。內核在掛載最終的 rootfs 之前,先從內存中掛載 initrd,加載必要的驅動后,先運行 initrd 中的 init 程序,掛載最終的 rootfs。然后執行 switch root 動作,切換至最終的 rootfs。
Alibaba Cloud Linux 2 采用 systemd 來管理用戶空間啟動流程,systemd 就是 init 程序,initrd 使用壓縮格式的initramfs 文件。因此在加載 initrd 之前,內核需要先解壓縮 initramfs。
cloud-init
在阿里云 ECS 環境中,cloud-init 是一個必不可少的初始化配置工具。在實例啟動階段能從多種數據源讀取相關數據并據此對虛擬機進行配置,如用戶密碼,主機名,網絡,用戶數據等等一些配置。
2、工欲善其事必先利其器
優化系統啟動時間,自然需要先對系統啟動畫像,了解啟動時間分布情況,找出系統啟動耗時熱點。
啟動時間測量
Linux 操作系統有如下常見的啟動時間測量統計方法:
systemd-analyze: systemd 自帶的啟動分析工具,能夠給出總的啟動時間消耗,已經用戶態服務啟動耗時統計。
dmesg: dmesg 輸出內核啟動日志,時間戳能夠幫助分析內核初始化各階段耗時情況。配合-d選項計算出日志間的時間差,方便快速定位內核啟動過程中耗時熱點。
initcall_debug: 內核啟動參數,開啟后會統計內核各初始化函數的耗時情況,相比dmesg -d更加精確。
printk/trace_printk: 要分析一些啟動熱點的細化耗時情況時,手動增加一些 printk/trace_printk 探針能夠幫助獲取時間統計信息。
ftrace: 必要時也可開啟內核早期 ftrace 功能,幫助分析熱點耗時。不過需要注意開啟 ftrace 后可能會導致函數延時增加,因此不宜參考 ftrace 得出函數絕對耗時,可以參照 trace 結果幫助分析熱點函數的耗時邏輯。
還有其他一些時間測試方法,以及圖形化畫像工具,這里不一一介紹。
啟動耗時熱點分析
對早期 Alibaba Cloud Linux 2 啟動進行測量畫像后,按耗時排序,得到如下耗時熱點:
| mem init | ~35 | 3.5% | 0.7% |
| ORC unwind init | ~90 | 9% | 1.8% |
| buddy init | 250 | 25% | 5% |
| console enable | ~60 | 6% | 1.2 % |
| initramfs unpack | 250 | 25% | 5% |
| free initmem | 270 | 27% | 5.4% |
| mouse probe | 650 | 65% | 13% |
| systemd initrd | 600 | N/A | 12% |
| mount rootfs | 200 | N/A | 4% |
| cloud init | 2740 | N/A | 54.8% |
采樣機器:ecs.g6.large 2C8G 實例
可見:
內核啟動階段,鼠標探測耗時占比較高。
總體啟動耗時中,一半以上的時間消耗在用戶態 cloud-init 進程上;
3、 快速啟動優化
常用啟動優化方法
常用的啟動優化方法大致如下:
瘦身
移除不必要的代碼,如模塊,服務等,縮減啟動初始化步驟;
移除不必要的測試,調式及打印;
精簡共享庫;
異步、并行
將耗時動作從關鍵路徑移除,延后執行;
將順序動作并行化執行 ;
原地執行(XIP): 多用于嵌入式系統;
定制化: 將通用初始化程序定制化 ;
算法優化: 改進算法,加速初始化時間。
我們的優化策略
去 initrd
從前面的啟動耗時熱點分析結果可以看出,initrd 解壓縮及 initrd systemd 耗時占了較大比率。
Alibaba Cloud Linux 2 只運行于阿里云云服務器上,系統盤設備基本固定為 virtio-blk 設備,根文件系統格式基本固定為 ext4 文件系統,去掉 initrd 方案應該可行,理論上會優化掉 initramfs unpack(270) + initrd systemd(560) ~ 800ms 的啟動耗時。于是開搞:
可見 initrd systemd 時間確實優化掉了,但是!總的啟動時間并沒有理論優化收益。
繼續探索原因,發現是內核啟動耗時增加了約 400ms。進一步分析發現,啟動耗時熱點之一的 mouse probe(600ms),去 initrd 之前是與 initrd systemd 并行執行的。
去掉initrd后,這部分時間就直接計入內核啟動時間了。抵去優化掉的 initramfs unpacking 的 200ms,內核實際增加了 400ms 左右。
因此,要最大化去 initrd 的優化收益,必須同時解決 mouse probe 的耗時。
延遲probe
通用 Linux 系統需要支持多種 IO 設備,而鼠標鍵盤是比較常用的輸入設備,特別是鼠標,產品繁多,接口多樣。系統啟動過程中加載鼠標驅動后,需要掃描多種 IO 總線來探測鼠標設備,這一過程非常耗時。
依據前面提到的優化方法,我們有兩種方案:
對云環境定制鼠標驅動,固定探測 virtio 設備;
將鼠標探測從啟動關鍵路徑剝離,延遲探測,與后面系統啟動服務并行;
第一種方案需要重構相關代碼,成本較高;而且定制化限制較多,無法與開源社區協作。因此需要思考第二種方法:延遲探測。一種簡單可行的方法是將原本內置(built-in)的設備驅動重新編譯為內核模塊(kernel module),因內核模塊存放在根文件系統,所以加載時機被動推遲到根文件系統掛載之后,此時內核已經啟動完成,自然與用戶態初始化進程并行執行。
測試結果如下:
帶 initrd 啟動
不帶 initrd 啟動
可見,內核啟動時間縮減約 200ms,優化掉 initrd systemd 時間;鼠標設備探測延后至 userspace 初始化階段,導致userspace 啟動時間略有增加。獲得預期的啟動時間優化。
內存初始化優化
內存初始化也是內核啟動熱點之一,特別是在大規格實例上,內存初始化耗時占比較高。圖中為 750GB 實例內存初始化耗時:
mem init 耗時近 2s
buddy init 耗時 1.8s
內存初始化動作是在內核啟動的關鍵路徑上,優化思路是并行初始化。因內存初始化時機較早,系統多CPU還未初始化完成,所以需要將內存初始化延后至CPU初始化完成之后,采用多線程并行執行內存初始化。這部分工作社區已經完成,通過內核配置deferred struct page init特性來開啟。
開啟后,內存初始化延后,按 NUMA node 并行執行:
前半部耗時約 0.2s
后半部耗時約 1.3s
free initmem 修復
早期 Alibaba Cloud Linux 2 啟動優化前有一個概率性的啟動熱點,free initmem 到 buddy 系統時,會大概率出現200ms 以上延時,dmesg 日志顯示如下,耗時超過 200ms:
1
[ ? 0.687494] rtc_cmos 00:00: setting system clock to 2020-03-03 15:09:38 UTC (1583248178)2
[ ? 0.915315] Freeing unused kernel image memory: 1836K總結
以上是生活随笔為你收集整理的uboot启动流程概述_Alibaba Cloud Linux 2 LTS OS 启动优化实践的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 十亿数据量运行速度慢_Java
- 下一篇: arthas 排查内存溢出_Java程序