前言
如果你把從源代碼開始編譯構建一個操作系統的工作當成廚師做一桌菜的話,Linux From Scratch(簡稱 LFS )就是一份“菜譜”。 從今天開始我准備寫系列教程,一步一步帶着大家從開源軟件的源代碼(大廚的“食料”)開始,基於最新版的 LFS(大廚的最新版“菜譜”)編譯出能運行的 Linux 操作系統、構建出能作為桌面日常使用的 Linux 操作系統、打包成可以在電腦上安裝的 Linux 操作系統、直至讓你做出跟 Deepin Linux 一樣好用的 GNU/Linux 發行版。這更是我們一步一步實踐的過程,也是我們逐步深入學習的過程。希望在走完這個過程后,我們的技術、能力能達到為 GNU/Linux 操作系統添磚加瓦,甚至走的更遠,作為一份子編制出我們自己的操作系統。
下面是我基於 LFS-11.0-systemd(以下簡稱 LFS11.0 )已經編譯構建好的 Linux 系統。完美無瑕,啟動了,登錄了,甚至可以上網了,你看下圖。
你心動了嗎? 不急, 跟着我,你只要 2 個小時,不要驚訝、就 2 個小時,你也能編譯、構建出能運行的 Linux 操作系統。作為《從LFS到自己的Linux發行版》系列教程的開篇,本篇會以最低難度、最明確步驟為宗旨,跟你一步到位體驗基於 LFS11.0 編譯、構建出能運行的 Linux 系統,讓你對 LFS 有個初步認識;力爭帶你一次成功,讓你樹立信心、獲得成就感。
第一節:LFS 准備工作
工欲善其事、必先利其器。為了順利地編譯構建你的 Linux 操作系統,我們該做好一些准備工作,免得過程中出問題、從頭再來,這樣的話 2 小時可是不能完成我們的 LFS 的啊。
-
平台准備:在我們日常使用的裝有 windows 操作系統的電腦任意硬盤上,准備不少於 200G 硬盤空間用於存放虛擬機(在這個電腦硬盤講 TB 的年代,為了將來的編譯不出問題,特別是需要一路拍攝快照的情況下,還是多准備點吧)。下載虛擬機軟件 VMware Workstation Pro 15.5.0(點此下載)並安裝。由於 Windows10 系統的原因,比 VMware Workstation Pro 15.5.0 更早的版本已經不能在 Windows10 系統下使用,如果已經安裝更新的版本可跳過此步。另外注意,你的電腦電源管理是否設置了休眠,如果是的話請取消這樣的設置。
-
虛擬機准備:我已經配置好了編譯構建 Linux 系統所需的虛擬機(即宿主機),並把該虛擬機 Deepin 上傳到我的百度網盤。你要做的是,下載該虛擬機(點此下載,提取碼 lfse),解壓到准備好的硬盤空間。例如下圖(不完全一致,下同)。
-
打開虛擬機:用虛擬機軟件 VMware Workstation 打開之前下載解壓的虛擬機 Deepin(就像用軟件 Word 打開 doc 文檔一樣,一層層目錄逐步深入尋找並打開),啟動前檢查網絡連接是否為橋接並把橋接模式設置為“已橋接至<你的物理機用的網卡>”,例如我的虛擬機已經橋接至我的電腦網卡 Intel(R) Centrino(R) Wireless-N 2200。
-
啟動虛擬機 :啟動虛擬機Deepin並登錄,用戶名、密碼都為 lfser。如果你的電腦內存大於 8G、CPU多於 8 線程,在打開虛擬機 Deepin 前調整虛擬機內存配置到計算機內存的一半、CPU 核數到計算機線程數的一半,以改善虛擬機 Deepin 的使用體驗、使其更流暢。
-
在虛擬機 Deepin 中復制必須的文件:把虛擬機 Deepin 桌面上文件夾 LFS-11.0-systemd全家桶 中的硬盤分區腳本 disk-partition.sh、LFS 源代碼包 lfs-packages-11.0.tar 和內核配置文件 myconfig-5.13.12 等三個文件復制到 lfser 的 home(即主目錄)中。LFS-11.0-systemd全家桶 文件夾中除了這三個文件,LFS11.0 手冊、參考文檔、LFS11.0 源代碼等都收納其中。
-
虛擬機 Deepin 中打開終端:雙擊虛擬機 Deepin 桌面底部 Dock 上的圖標打開深度終端。在已經打開的深度終端輸入代碼
sudo su
並根據終端要求輸入系統管理員密碼 lfser,如下圖。
-
打開源代碼:從桌面上文件夾 LFS-11.0-systemd全家桶 中找到文件 LFS_code-4.2.0,雙擊並選“顯示”,系統自動加載代碼編輯器 sublime 並打開該代碼文件。
至此,我們為 LFS11.0 所做的准備工作全部完畢。
第二節:一步完成你的 LFS11.0
這一節,我們通過復制粘貼一步完成 LFS11.0 。我們的基於 LFS11.0 編譯構造自己的 Linux 操作系統的工作都將在虛擬機 Deepin 中進行。
- 復制粘貼代碼一步完成LFS:在代碼編輯器 sublime 打開的代碼文件 LFS_code-4.2.0 中復制全部代碼並粘貼到之前已經通過輸入
sudo su
命令獲得管理員權限的深度終端中運行。這一步 :Ctrl+C & Ctrl+V,已經足夠、你只須等待,深度終端不斷運行輸入的代碼,直至 LFS 完成、虛擬機關機。有些宿主機,在切換shell時,終端會停止運行,如果停止運行,請從停止處繼續復制粘貼后續代碼。可能停止處,代碼中已經標明此處須等運行完畢再粘貼后續代碼
。
深度終端運行這些代碼期間,在不斷地進行源代碼的編譯、Linux 系統的構建,你會持續地看到終端出現如下的滾屏。
在此期間,你不要關機(你的電腦、虛擬機 Deepin 都不要關閉),不要在深度終端輸入任何字符,也盡量不要在虛擬機 Deepin 中打開其他窗口。你最好是把虛擬機 Deepin 最小化到你電腦的任務欄上,以免由於虛擬機 Deepin 內存不足或者 CPU 高占用而導致出現問題。
為了直觀地了解虛擬機 Deepin 在這運行的 2 小時中,深度終端到底做了些什么,把我基於 LFS11.0 並做了適當調整的一部分代碼粘貼於下面,本文不做詳深度解析(那正是下一篇所要呈現給大家的),如果暫時不想了解,盡管可以路過。
#############################################################
##### LFS,let's go! #####
#############################################################
########## II. Preparing for the Build ##########
########## Chapter 2. Preparing the Host System
# sudo su
# apt-get update
# Deepin15以外的宿主機需要安裝的軟件根據不同的宿主機確定
# apt-get install bison texinfo g++ -y
# ln -fs /bin/bash /bin/sh
#############################################################
##### 分界線(此處以上代碼在准備階段已經運行完畢) #####
#############################################################
fdisk -l
bash disk-partition.sh
mkfs -v -t ext4 /dev/sdb1
mkswap /dev/sdb2
##########
export LFS=/mnt/lfs
##########
mkdir -pv $LFS
mount -v -t ext4 /dev/sdb1 $LFS
/sbin/swapon -v /dev/sdb2
########## Chapter 3. Packages and Patches
mkdir -v $LFS/sources
chmod -v a+wt $LFS/sources
# 注意解壓后的目錄名
tar xvf lfs-packages-11.0.tar
cp -R 11.0/* $LFS/sources
cp myconfig-5.13.12 $LFS/sources
rm -rf 11.0
pushd $LFS/sources
md5sum -c md5sums
popd
########## Chapter 4. Final Preparations
mkdir -pv $LFS/{etc,var} $LFS/usr/{bin,lib,sbin}
for i in bin lib sbin; do
ln -sv usr/$i $LFS/$i
done
case $(uname -m) in
x86_64) mkdir -pv $LFS/lib64 ;;
esac
mkdir -pv $LFS/tools
##########
groupadd lfs
useradd -s /bin/bash -g lfs -m -k /dev/null lfs
echo "lfs:lfser" | chpasswd
chown -v lfs $LFS/{usr{,/*},lib,var,etc,bin,sbin,tools}
case $(uname -m) in
x86_64) chown -v lfs $LFS/lib64 ;;
esac
chown -v lfs $LFS/sources
[ ! -e /etc/bash.bashrc ] || mv -v /etc/bash.bashrc /etc/bash.bashrc.NOUSE
su - lfs
##########
cat > ~/.bash_profile << "EOF"
exec env -i HOME=$HOME TERM=$TERM PS1='\u:\w\$ ' /bin/bash
EOF
cat > ~/.bashrc << "EOF"
set +h
umask 022
LFS=/mnt/lfs
LC_ALL=POSIX
LFS_TGT=$(uname -m)-lfs-linux-gnu
PATH=/usr/bin
if [ ! -L /bin ]; then PATH=/bin:$PATH; fi
PATH=$LFS/tools/bin:$PATH
CONFIG_SITE=$LFS/usr/share/config.site
export LFS LC_ALL LFS_TGT PATH CONFIG_SITE
EOF
source ~/.bash_profile
########## III. Building the LFS Cross Toolchain and Temporary Tools mportant Preliminary Material ##########
########## Chapter 5. Compiling a Cross-Toolchain
# 設置4線程編譯,具體根據宿主機可用的線程數設置MAKEFLAGS
export MAKEFLAGS='-j4'
cd $LFS/sources
##########
tar xvf binutils-2.37.tar.xz
cd binutils-2.37
mkdir -v build
cd build
../configure --prefix=$LFS/tools \
--with-sysroot=$LFS \
--target=$LFS_TGT \
--disable-nls \
--disable-werror
make
make install -j1
# 退出build目錄
cd ..
cd ..
rm -rf binutils-2.37
##########
#
#
#
# 中間省略3000行
#
#
#
##########
grub-install /dev/sdb
cat > /boot/grub/grub.cfg << "EOF"
# Begin /boot/grub/grub.cfg
set default=0
set timeout=5
insmod ext2
set root=(hd0,1)
menuentry "GNU/Linux, Linux 5.13.12-lfs-11.0-systemd" {
linux /boot/vmlinuz-5.13.12-lfs-11.0-systemd root=/dev/sdb1 ro tsc=reliable pmtmr=0x0
}
EOF
########## Chapter 11. The End
echo 11.0-systemd > /etc/lfs-release
cat > /etc/lsb-release << "EOF"
DISTRIB_ID="Linux From Scratch"
DISTRIB_RELEASE="11.0-systemd"
DISTRIB_CODENAME="KhaKha"
DISTRIB_DESCRIPTION="Linux From Scratch"
EOF
cat > /etc/os-release << "EOF"
NAME="Linux From Scratch"
VERSION="11.0-systemd"
ID=lfs
PRETTY_NAME="Linux From Scratch 11.0-systemd"
VERSION_CODENAME="KhaKha"
EOF
##########
logout
#############################################################
###### Deepin15以外宿主機此處需等運行完畢再粘貼后續代碼 #####
#############################################################
umount -Rv $LFS
shutdown now
#############################################################
##### LFS,that's enjoy! #####
#############################################################
# 1、通過增加內核啟動參數tsc=reliable pmtmr=0x0,解決了clocksource問題(4.0.2-2021.12.13)
# 2、更改成無人值守版本用於在Deepin 15.5編譯(4.1.1-2021.12.16)
# 3、預設的內核配置文件換成myconfig-5.13.12(4.1.2-2021.12.16)
# 4、改正inetutils配置代碼錯誤(4.1.3-2021.12.20)
# 5、改正glibc安裝時缺失的兩條命令(4.1.3-2021.12.21)
# 6、myconfig-5.13.12增加CONFIG_RANDOM_TRUST_CPU=y (4.1.3-2021.12.22)
# 7、改正了創建/etc/passwd、/etc/group文件命令和gcc安裝時切換目錄命令的位置(4.1.4-2021.12.25)
# 8、修改了基本網絡配置,用可預見的設備命名而不是傳統命名來命名網絡適配器名字,采用systemd-resolved配置DNS(4.1.5-2021.12.27)
需要復制粘貼到深度終端的全部代碼,我已經上傳到百度網盤,可以下載(點此下載 ,提取碼 lfse)、在下一篇開始前提前閱讀一下,並與 LFS11.0 手冊做個對比,看有什么不同。注意,無論是在你電腦的 Windows 系統中,還是虛擬機 Deepin 中,打開、編輯代碼的最好工具是各種代碼編輯器,推薦 sublime;千萬不要用 Word、WPS 等文檔編輯器去打開、編輯代碼;在網頁、PDF 文檔中復制的代碼,也需要粘貼在代碼編輯器並加以檢查后才能使用。
你的虛擬機在運行 2 小時后,基於 LFS11.0 的 Linux 系統已經構建好,虛擬機 Deepin 會自動關機、並等你開啟你的 Linux 系統。(如果你的虛擬機窗口最小化到你電腦的任務欄了,那么雙擊任務欄上的虛擬機圖標)你會看到如下窗口。
第三節:開啟你的 LFS 系統
上節,我已經說了,你的電腦(當然是虛擬機 Deepin)在把代碼全部復制粘貼到深度終端並運行約 2 小時后,已經完全編譯構建好了一個基於 LFS11.0 的 Linux 操作系統。那么,深度終端到底做了些什么、你的電腦到底發生了哪些變化呢?
下面這張圖是,我們的虛擬機 Deepin 剛剛開啟的時候的系統目錄。
可以看出,內置磁盤只有一個:系統盤。
再下面一張圖,是基於 LFS11.0 編譯構建 Linux 操作系統后的虛擬機 Deepin 的系統目錄:
可以看出,內置磁盤有兩個:系統盤、48GB 卷(從名字可以看出已經分區、格式化並掛載),多出了一個內置磁盤 48GB 卷。這個多出來的內置磁盤,就是我們通過把代碼復制粘貼到深度終端並回車運行,把虛擬機上已經有的第二硬盤進行了分區,並對分區進行了格式化、掛載,形成了可以被電腦所用的硬盤分區。
那么,這個之前剛剛分區、格式化的硬盤分區(即 48GB 卷)現在里面有什么呢?我們再看下圖。
哇,里面不再是像剛剛被格式化、空空如也的樣子了,里面已經有 bin、boot 和 home 等一系列目錄,儼然是一個完整的 Linux 操作系統。對,這就是深度終端在運行 2 小時后編譯構建完成的 Linux 系統,只等你開啟。
下面,你跟着我一起來開啟你的 Linux 系統吧。
-
進入虛擬機 Deepin 的 BIOS 設置狀態:我們的虛擬機 Deepin 的 BIOS 默認設置從第一硬盤啟動,如果現在馬上開機(當然是虛擬機 Deepin),那么所運行的還是第一硬盤所裝的 Deepin 操作系統,並不是你所編譯構建的 Linux 系統。下面,我們就來設置吧。在虛擬機軟件 VMware Workstation 的菜單欄,點啟動按鈕(紅色箭頭)右邊的向下箭頭,即出現啟動菜單,在該菜單選“打開電源時進入固件”選項,虛擬機 Deepin 即進入 BIOS 設置狀態。
-
設置虛擬機 Deepin 從第二硬盤啟動:進入了 BIOS 設置狀態、並設置成如下圖第二硬盤 Hard Drive (0,1) 在上、第一硬盤 Hard Drive (0,0) 在下的狀態,並保存、退出,虛擬機 Deepin 即自動重啟。
-
登錄你的 Linux 系統:虛擬機 Deepin 的 BIOS 設置完畢、保存退出后,你的電腦 (虛擬機 Deepin)即自動重啟,並很快進入你的 Linux 系統登錄狀態,輸入用戶名 root(還沒創建其他用戶,現在只能以 root 用戶登錄)和密碼 lfser(這個密碼是我在代碼中設置的,你可以在代碼中設置任意密碼,或者在登陸后輸入命令
passwd root
重新設置),你的 Linux 系統真的登錄成功了。
-
試用你的Linux系統:在登錄成功后,除了登錄信息,電腦顯示的就是一個黑乎乎的屏幕,她真的能為我們所用嗎?能連接網絡嗎?我們在電腦中輸入命令
ping www.baidu.com
來檢查一下網絡是否連接,看看出現什么情況。噢 ,她已經聯網了,ping 出了百度網的網址、已經接收了 4 個信息包(4 packets received),當然她還能接收更多信息包,但我按 Ctrl+C 鍵人為地停止了這個過程 。
That's Wonderful!這真是令人激動的時刻。
我已經把剝離了宿主機系統的 LFS 11.0 虛擬機導出、上傳到百度網盤,歡迎下載試用(點此下載,提取碼 lfse)。打開 LFS 11.0 系統后,對比一下系統中 /etc/fstab 和 、/boot/grub/grub.cfg 兩個文件與 LFS 時形成的這兩個文件的區別,思考一下為什么要做這些改變,為后續的學習做點鋪墊。
結語
你跟我一起,一步一步走來,真的從源代碼開始,編譯構造出了你的 Linux 操作系統 。盡管這個系統還很單薄、功能不是特別多,還不能輸入、顯示漢字,還沒有視窗;你的這個 Linux 操作系統的編譯構造過程,是用我配置好的虛擬機 Deepin,把我根據 LFS11.0 手冊整理並適當改造了的代碼直接粘貼到深度終端,體驗了一次編譯構造 Linux 系統的過程,你對編譯構造的原理還不是很明了。
這正是我以后要跟你們繼續做的事情:詳細了解從源代碼到你的 Linux 系統的編譯構造過程,基於 BLFS 構造出能用於工作的功能豐富的 Linux 系統,把你的 Linux 系統裝入 U 盤並能在別的電腦(不是虛擬機、也不是限於自己的電腦)、為別人所用,直至最終構造出像 Deepin Linux 一樣好用的、有完整的包管理機制的 Linux 操作系統。
這里要順便表揚一下 Deepin Linux 。在我試用過的 GNU/Linux 操作系統中,這個 Linux 系統是最接地氣的,完全開箱即用,中文、輸入法及常規軟件統統搞定,我用這個系統進行 LFS 時,只做了三項簡單設置:一、通過深度軟件商店安裝了 sublime 這個代碼編輯器;二、通過深度終端安裝了 g++ 等三個 LFS 編譯環境必須的軟件;三、通過深度終端對 sh 指向由 dash 改為 bash。這個系統,還特別漂亮,用來有蘋果系統的感覺。真不愧是我們自主操作系統的佼佼者!
如果我們一步一步走過了上述的全部過程,我相信對你我都有所裨益,能深刻理解操作系統構造原理,有能力去為 GNU/Linux 這個偉大的自由開源軟件添磚加瓦,甚至走的更遠,去創造出完全為我們所有的操作系統。等着那一天!