第 1章
準備工作
本書詳細解剖了DIM-SUM作業系統的原始碼。DIM-SUM作業系統是本書作者謝寶友在過去幾年中,陸續實現的一個作業系統。它的版權遵循GPL V2開源軟體協議。
由於DIM-SUM是一個不斷發展中的作業系統,因此本書以其第一個釋出版本為基礎進行剖析。這個版本的名稱是:HOT-POT。以後的版本可能會被稱為“dumpling”、“noodle”,總之是我們能夠想到的中國小吃名稱🙂
1.1. DIM-SUM簡介
1.1.1. 為什麼是HOT-POT?
HOT-POT意為火鍋,是非常有川渝特色的地方美食。之所以取這個名稱,主要有如下原因:
1、四川是作者的故鄉,並且作者來到成都已經有20多年了。對這個城市的火鍋印象深刻!
2、紅通通的火鍋,有鮮明的民族烙印,代表了喜慶、熱鬧、歡快的含義。
3、如果您真的吃過火鍋,那麼可能忘不了它的辣,一定不能小瞧它,並且久久不能忘懷以至於想要多嘗幾次。希望這款作業系統也能帶給您這樣的感覺。
1.1.2. DIM-SUM是什麼
如果說目前的DIM-SUM是一個完美的作業系統,那無疑是一個謊言。但是,如果說這個作業系統就僅僅是一個茶餘飯後的談資,那無疑也是另一個謊言。
最基本的,希望它可供作業系統愛好者用於學習目的,並且作者相信這完全沒有問題。但是,作者的目的不僅僅是如此。其遠大的標的,是實現一款工業級伺服器作業系統。簡而言之,就是一款可以在生產環境下麵使用的,可以在伺服器和個人電腦上面正常執行的作業系統。當然了,這樣的一款作業系統必然也能夠執行在嵌入式裝置中。例如,執行在電視、電錶、攝像頭、手錶,以及其他一些我們能夠想象得到的嵌入式裝置中。
任何心智正常的人,都知道實現這樣的作業系統是一件很難的事情。讀者可能忍不住想問:為什麼作者您想去做這麼一件很難,並且可能沒有什麼收益,也許還會讓您招致恥笑的笨事呢?難道您真的是一個笨蛋?
作者也忍不住這樣回答質疑:
1、是的,作者確實是一個笨蛋。但是古語說的好:聰明人下笨功夫!
2、正如作者在其譯作《深入理解並行程式設計》一書的譯者序中所說:
20年前,當我正式成為一名軟體工程師的時候,就有一個夢想:開發一款作業系統。那時候,雖然知道Linux的存在,但是實在找不到一臺可以正常安裝使用Linux的PC。因此只能閱讀相關的原始碼分析書籍而不能動手實踐。
在浮躁的年代,談論夢想可能一件不合時宜的行為。然而有什麼辦法呢?這畢竟真的是20年前的夢想,難道您想讓我撒謊?
3、開源軟體運動,已經為我們實現作業系統提供了現實可能性。首先,象Linux這樣的開源作業系統為我們提供了很好的基礎,這樣我們可以從開源軟體中學習到不少的技能、方法、設計思路。其次,開源軟體允許分散在各地的開發者協同工作,集思廣益的開發作業系統。作者在Linux社群中,作為ARM/ZTE ARCHITECTURE的Maintainer,對此深有體會。
4、作業系統是IT行業的核武器。到目前為止,我們還處於“缺芯少魂”的狀態,其中的“魂”就是作業系統。真正核心的軟體,需要一代人,甚至幾代人耐心的雕琢,而不能寄希望於短時間內產生立竿見影的效果。換句話說,要有“板凳一坐十年冷”的心態來做這件事。有了這樣的心態,就不會覺得難。
5、從另一個角度來說:萬古長空,一朝風月。任何難事,一旦想要去做,就需要把握當下。空談誤國,實幹方能興邦。即使這件事情很難,但是不動手永遠不會有任何結果。況且,作者喜歡有挑戰性的事情,例如:寫一個工業級伺服器作業系統🙂
目前,DIM-SUM已經實現瞭如下功能:
1、arm 64 qemu小系統,含記憶體、時鐘初始化。
2、全域性優先順序排程模組,排程演演算法類似於Linux實時排程。
3、記憶體管理模組,包含頁面管理、beehive分配器。
4、相容linux ext3的LEXT3檔案系統。
5、塊裝置層實現。
6、集成了LWIP網路協議棧。
7、移植了常用的核心態C庫API。
8、實現了一個粗糙的命令控制檯。
總之,作者認為HOT-POT是DIM-SUM作業系統的Good Start。在後續的開發過程中,作者懷著熱切的心情,期待您參與到它的開發中來。
1.1.3. DIM-SUM歡迎什麼?
任何建設性對抗性質的建議、穩定優雅的程式碼、BUG報告、測試、社群建設等等,都是DIM-SUM所歡迎的!
1.1.4. DIM-SUM不歡迎什麼?
我們不歡迎空談和只會報怨的人。雖然我們知道,DIM-SUM並不完善,您有很多噴它的理由。
1.2. 獲得原始碼
Paul E.Mckenney曾經說過:
If you want to do cool things, it is necessary to invest large amounts of time learning and (especially!) practicing.
誠哉斯言!
請讀者相信我這個20年傳奇工匠程式員的經驗:要深刻的理解象Linux作業系統這樣的複雜程式碼,必須要動手實踐,對著原始碼看書!
本書也不會大量的貼上DIM-SUM原始碼,這是故意為之的。目的是逼迫讀者下載原始碼並對照著原始碼閱讀本書。
要獲得本書配套原始碼,您有兩種方式:
1.直接透過網頁下載
2.透過git獲取原始碼
1.2.1. 透過網頁下載原始碼
透過網頁下載原始碼是最簡單快捷的方式。您可以透過如下兩個網址下載DIM-SUM的原始碼:
1.https://download.csdn.net/user/xiebaoyou/
2.http://blog.chinaunix.net/uid-25845340-id-5785292.html
將下載的原始碼包命名為dim-sum.20180519.tar.bz2。為了防止下載過程中,由於網路原因導致的檔案損壞,您可以驗證原始碼包的MD5值。在ubuntu 16.04系統中,可以在命令列控制檯輸入如下命令來得到原始碼包的MD5值:
md5sum dim-sum.20180519.tar.bz2
正確的MD5值應當是:
e888c22b47adcb266382e1791bb729f8
關於DIM-SUM作業系統的新訊息,我也會透過部落格釋出,地址是:
http://blog.chinaunix.net/uid/25845340.html
透過網頁下載原始碼,可以滿足閱讀本書的要求。但是,它滿足不了您如下的要求:
1.獲得DIM-SUM作業系統最新的原始碼
2.查閱DIM-SUM作業系統的補丁記錄
下一步將討論如何透過git獲得原始碼。這也是作者推薦的方式。
1.2.2. 透過git獲取原始碼
無論怎樣強調git在開源專案中的重要性都不過分。作者甚至推薦您找一本git簡明手冊仔細讀一讀。
假設您的系統中已經安裝好git工具。您可以透過如下命令獲取DIM-SUM作業系統的原始碼。
git clone https://code.csdn.net/xiebaoyou/dim-sum.git
這個命令會在您的當前目錄中建立一個名為dim-sum的子目錄,並將DIM-SUM作業系統的程式碼下載到本地。
小問題1.1:嘿!看起來您是想讓讀者在Linux環境下閱讀並除錯程式碼,但是Linux環境閱讀程式碼是否真的方便。為什麼不在書中直接貼出所有程式碼,您用意何在?
當然,對於大多數讀者來說,不僅僅想對照著原始碼閱讀本書。他們還希望:
1、跟蹤DIM-SUM的最新版本。
2、查閱DIM-SUM的補丁記錄,明白每一個補丁的作用,與補丁的作者聯絡。
3、給DIM-SUM提交補丁。
4、在DIM-SUM中新增自己的程式碼。
5、在PC中除錯DIM-SUM的程式碼。
這樣的讀者需要仔細閱讀下一節的內容。
1.3. 搭建除錯開發環境
雖然透過上一節的方法獲得原始碼以後,您將能夠順利的閱讀本書。但是有一句話說得很正確:紙上得來終覺淺,絕知此事要躬行。因此強烈建議您按照本節的方法搭建除錯開發環境。
1.3.1. 安裝ubuntu 16.04
作者的筆記本中,安裝的作業系統是ubuntu 16.04,因此可以確保本節中的除錯開發環境能順利的執行在ubuntu 16.04系統中。其他的Linux版本應該也是可以的,但是作者並不完全保證其他版本完全正常工作。
首先,您需要在如下連結中下載ubuntu 16.04的安裝映象:
http://old-releases.ubuntu.com/releases/16.04.3/
視您的開發環境PC 機CPU配置,您可以下載不同的安裝映象:
1.64位PC,透過如下連結下載
http://old-releases.ubuntu.com/releases/16.04.3/ubuntu-16.04-desktop-amd64.iso
2.32位PC,透過如下連結下載
http://old-releases.ubuntu.com/releases/16.04.3/ubuntu-16.04-desktop-i386.iso
在http://old-releases.ubuntu.com/releases/16.04.3/MD5SUMS中,有這兩個映象檔案的MD5值,分別為:
c94d54942a2954cf852884d656224186
610c4a399df39a78866f9236b8c658da
請檢查下載檔案的MD5值,確保與上面兩個值一致。
小問題1.2:呃,您已經兩次提到MD5值了,它有那麼重要嗎?
有兩種方法安裝您的ubuntu 16.04。
第一種方法,是直接在物理機上安裝ubuntu 16.04。建議您找一臺Linux機器,並使用dd命令將映象燒寫到USB中,並透過USB來安裝系統。
第二種方法,是在虛擬機器中安裝ubuntu 16.04。這種方法可以不用將安裝映象燒寫到USB中。在虛擬機器中實際搭建開發環境,其效果和物理機中是一致的。
ubuntu 16.04的安裝過程比較簡單,這裡不再詳述。
小問題1.3:可是我沒有Linux環境,也不知道怎麼用dd命令來燒寫映象到USB?
為了方便Linux新手,後續假設您是在虛擬機器中安裝ubuntu 16.04。並以此為基礎搭建除錯開發環境。
1.3.2. ubuntu 16.04環境配置
首先,請配置您的虛擬機器,為它建立兩個網絡卡。
作者在Oracle VM VirtualBox管理器中,是透過“設定”->“網路”進入配置介面。
在“網絡卡1”標簽介面中,選擇“啟用網路連線”,併在“連線方式”中選擇“僅主機(Host-Only)配接器”,在“介面名稱”中選擇“vboxnet0”。該網絡卡用於虛擬機器與物理機的檔案共享連線。
在“網絡卡2”標簽介面中,選擇“啟用網路連線”,併在“連線方式”中選擇“網路地址轉換(NAT)”。該網絡卡用於虛擬機器與網際網路的連線。後面我們將會看到,無論是安裝軟體包,還是透過git下載程式碼,都需要連線到網際網路。
第二步,啟動ubuntu 16.04虛擬機器,進行如下基本環境配置:
1、開啟命令列控制檯,在作者的環境中,是透過按“ctrl+alt+t”實現的。
2、在控制臺中,輸入如下命令切換到root使用者。當然,為了防止誤操作損壞系統,您也可以不用切換到root使用者,但是請記得為後續的某些操作新增sudo字首。
sudo -s
3、在控制臺中,輸入如下命令更新apt倉庫:
apt-get update
視您的網路狀態而定,這一步可能需要花費數分鐘的時間。
由於您還沒有正確的配置雙網絡卡,因此您的虛擬機器還不能正確的連線到網際網路。這時可以簡單的禁止第一個網絡卡。
4、在控制臺中,輸入如下命令安裝vim:
apt-get install vim
5、編輯/etc/network/interfaces,輸入如下內容:
# interfaces(5) file used by ifup(8) and ifdown(8)
auto lo
iface lo inet loopback
auto enp0s3
iface enp0s3 inet static
address 192.168.0.98
netmask 255.255.255.0
auto enp0s8
iface enp0s8 inet dhcp
其中enp0s3是作者建立的虛擬機器中的內網網絡卡,用於虛擬機器與主機之間的通訊,在您的機器上可能是其他名稱,請註意調整。192.168.0.98是該網絡卡的地址,請根據您的實際配置進行調整。
enp0s8則是作者建立的虛擬機器中的外網網絡卡,用於虛擬機器與網際網路之間的通訊,在您的機器上可能是其他名稱,請註意調整。
編輯並儲存/etc/network/interfaces檔案後,請執行如下命令重啟網路服務,使配置生效:
/etc/init.d/networking restart
第三步,執行如下命令建立工具目錄:
mkdir /hot-pot
小問題1.4:一定要在根目錄下建立hot-pot目錄嗎?其他目錄名稱可以嗎?
1.3.3. 搭建編譯環境
首先,您需要在ubuntu 16.04中安裝git工具。在控制臺中輸入如下命令開始安裝:
apt-get install git
執行完畢後,在控制臺中輸入如下命令驗證git工具是否正確安裝:
git –version
如果看到如下控制檯輸出,則表示git工具安裝成功:
git version 2.7.4
第二步,透過git工具下載輔助工具。可以透過如下命令獲取這些工具:
cd /hot-pot/
git clone https://code.csdn.net/xiebaoyou/assistant.git
由於assistant這個git倉庫中包含了數百M的工具鏈,可能會花費數分鐘甚至一個小時的時間,請耐心等待。完成後,透過如下命令檢視是否下載成功:
ls assistant -al
在控制臺上,應當看到如下輸出:
總用量 44
drwxrwxr-x 5 xiebaoyou xiebaoyou 4096 5月 20 15:12 .
drwxrwxr-x 31 xiebaoyou xiebaoyou 4096 5月 20 20:04 ..
drwxrwxr-x 2 xiebaoyou xiebaoyou 4096 5月 20 15:12 gcc-linaro-5.3
drwxrwxr-x 8 xiebaoyou xiebaoyou 4096 5月 20 15:15 .git
drwxrwxr-x 2 xiebaoyou xiebaoyou 20480 5月 19 17:16 hot-pot.toolchains.4.9.3
-rw-rw-r– 1 xiebaoyou xiebaoyou 15 5月 19 16:45 README.md
第三步,您需要安裝編譯工具鏈。要編譯HOT-POT,需要gcc 4.x版本的交叉編譯工具鏈。作者已經將相應的工具鏈放到assistant/hot-pot.toolchains.4.9.3中。
在控制臺中執行如下命令,獲得hot-pot.toolchains.4.9.3.tar.bz2工具鏈壓縮包:
cd /hot-pot/assistant/hot-pot.toolchains.4.9.3
cat x* > hot-pot.toolchains.4.9.3.tar.bz2
其中第二條命令將hot-pot.toolchains.4.9.3目錄中所有檔案合併,生成壓縮包檔案。
然後使用如下命令檢查生成的壓縮包是否正確:
md5sum hot-pot.toolchains.4.9.3.tar.bz2
您將會看到如下輸出:
3cdfaf72c2fe82535c596414fd4b026c hot-pot.toolchains.4.9.3.tar.bz2
如果輸出的MD5值不是“3cdfaf72c2fe82535c596414fd4b026c”,則說明下載過程有誤,生成的工具鏈壓縮包不正確。
在控制臺中輸入如下命令,將壓縮包解壓,獲得可以執行的工具鏈:
tar xvjf hot-pot.toolchains.4.9.3.tar.bz2 -C ../
在控制臺中輸入如下命令,檢查工具鏈是否能夠正常執行:
/hot-pot/assisant/aarch64-linux-gnu/bin/aarch64-linux-gnu-gcc –version
如果在控制臺中看到如下輸出,那麼恭喜您:
aarch64-linux-gnu-gcc (GCC) 4.9.3
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
第四步,您需要安裝gdb工具。這樣我們就能夠象除錯應用程式那樣,對DIM-SUM作業系統進行單步跟蹤除錯了。這對於深入理解DIM-SUM作業系統有極大的幫助。因此,強烈建議您安裝這個工具。
在Linaro gcc 5.3工具鏈中,已經包含了gdb工具。
同樣的,作者在已經將Linaro gcc 5.3工具鏈放到assistant/gcc-linaro-5.3中。
您可以在控制臺中輸入如下命令,來生成Linaro gcc 5.3工具鏈壓縮包:
cd /hot-pot/assistant/gcc-linaro-5.3
cat x* > gcc-linaro-5.3-2016.02-x86_64_aarch64-elf.tar.bz2
同樣的,請使用md5sum命令檢查壓縮包是否正確:
md5sum gcc-linaro-5.3-2016.02-x86_64_aarch64-elf.tar.bz2
您應當在控制臺中看到如下輸出。
e1b129d60b2b8e6f398014057f514b34 gcc-linaro-5.3-2016.02-x86_64_aarch64-elf.tar.bz2
同樣的,請註意MD5值應當為“e1b129d60b2b8e6f398014057f514b34”。
在控制臺中輸入如下命令,將工具鏈解壓:
tar xvjf gcc-linaro-5.3-2016.02-x86_64_aarch64-elf.tar.bz2 –C ../
在控制臺中輸入如下命令,確認gdb工具是否正常:
/hot-pot/assistant/gcc-linaro-5.3-2016.02-x86_64_aarch64-elf/bin/aarch64-elf-gdb -v
如果一切正常,您將在控制臺中看到如下輸出:
GNU gdb (Linaro GDB 2016.02) 7.10.1.20160210-cvs
第五步,透過git下載原始碼。在控制臺中輸入如下命令:
cd /hot-pot/
git clone https://code.csdn.net/xiebaoyou/dim-sum.git
這一步很快就能夠完成,因為DIM-SUM目前的程式碼規模還不算大🙂
第六步,檢出HOT-POT程式碼,在控制臺中輸入如下命令:
git checkout -b hot-pot v0.1
該命令會在您的git倉庫中建立一個hot-pot分支,並將v0.1版本的程式碼檢出。其中v0.1版本是DIM-SUM的HOT-POT版本。
是不是迫不及待的想為HOT-POT編譯出一個可以執行的版本?請接著看下一節。
1.3.4. 編譯HOT-POT
編譯HOT-POT的方法很簡單。如果您編譯過Linux原始碼,應該對下麵的命令非常熟悉:
cd /hot-pot/dim-sum/
make ARCH=arm64 qemu_defconfig
make ARCH=arm64 EXTRA_CFLAGS=”-g -D__LINUX_ARM_ARCH__=8 -DCONFIG_QEMU=1″ CROSS_COMPILE=/hot-pot/assistant/aarch64-linux-gnu/bin/aarch64-linux-gnu- Image dtbs
如果在控制臺中看到如下輸出資訊,則表示編譯成功:
CC usr/shell/sh_symbol.o
CC usr/shell/sh_task.o
CC usr/shell/sh_memory.o
CC usr/shell/sh_register.o
LD usr/shell/built-in.o
LD usr/built-in.o
LD vmlinux.o
MODPOST vmlinux.o
WARNING: modpost: Found 20 section mismatch(es).
To see full details build your kernel with:
‘make CONFIG_DEBUG_SECTION_MISMATCH=y’
GEN .version
CHK include/generated/compile.h
UPD include/generated/compile.h
CC init/version.o
LD init/built-in.o
LD .tmp_vmlinux1
KSYM .tmp_kallsyms1.S
AS .tmp_kallsyms1.o
LD .tmp_vmlinux2
KSYM .tmp_kallsyms2.S
AS .tmp_kallsyms2.o
LD vmlinux
SYSMAP System.map
SYSMAP .tmp_System.map
OBJCOPY arch/arm64/boot/Image
Kernel: arch/arm64/boot/Image is ready
目前,HOT-POT借用了Linux的編譯框架,因此輸出的符號表檔案仍然是“vmlinux”,正如上圖中“LD vmlinux”一行所示。當然,如果您能夠提交一個補丁來修正這些問題,我們會非常感激的。
小問題1.5:您為什麼不詳細解釋一下編譯命令,就象大多數書籍中那樣?
在控制臺中輸入如下命令,看看HOT-POT映象是否生成成功:
ls arch/arm64/boot/Image -al
預期的結果大概是這樣的:
-rwxrwxr-x 1 xiebaoyou xiebaoyou 1066496 5月 21 10:07 arch/arm64/boot/Image
小問題1.6:我的天,生成的映象竟然超過1M?
1.3.5. 執行HOT-POT
要執行HOT-POT,您需要安裝qemu。這為您免除了購買單板的需要。在控制臺中,輸入如下命令:
apt-get install qemu
安裝完成後,請使用如下命令確認成功安裝qemu模擬器:
qemu-system-aarch64 –version
您應當在控制臺中看到如下輸出:
QEMU emulator version 2.5.0 (Debian 1:2.5+dfsg-5ubuntu10.28), Copyright (c) 2003-2008 Fabrice Bellard
執行如下命令,在qemu中啟動HOT-POT:
cd /hot-pot/dim-sum/
sudo qemu-system-aarch64 -machine virt -cpu cortex-a53 -m 512 -kernel arch/arm64/boot/Image -drive file=./disk.img,if=none,id=blk -device virtio-blk-device,drive=blk -device virtio-net-device,netdev=network0,mac=52:54:00:4a:1e:d4 -netdev tap,id=network0,ifname=tap0 –append “earlyprintk console=ttyAMA0 root=/dev/vda rootfstype=ext3 init=/bin/ash rw ip=10.0.0.10::10.0.0.1:255.255.255.0:::off”
現在,您看到的應該是如下空白視窗:
別急,按“ctrl+alt+2”看看。激動人心的介面應當出現了,如下:
在這個介面中回車,並輸入ls命令,您將會看到如下介面:
小問題1.7:但是請等一等,我想看看前面的輸出,該怎麼辦?
看起來大功告成,但是似乎還缺少一點什麼東西?
1.3.6. 開始除錯
在前面的步驟中,我們已經將gdb除錯工具解壓到:
/hot-pot/assistant/gcc-linaro-5.3-2016.02-x86_64_aarch64-elf/bin/aarch64-elf-gdb
現在是時候用用它了。
首先應當換一種方式啟動HOT-POT,使用如下命令:
sudo qemu-system-aarch64 -machine virt -cpu cortex-a53 -m 512 -s -S -kernel arch/arm64/boot/Image -drive file=./disk.img,if=none,id=blk -device virtio-blk-device,drive=blk -device virtio-net-device,netdev=network0,mac=52:54:00:4a:1e:d4 -netdev tap,id=network0,ifname=tap0 –append “earlyprintk console=ttyAMA0 root=/dev/vda rootfstype=ext3 init=/bin/ash rw ip=10.0.0.10::10.0.0.1:255.255.255.0:::off”
請註意該命令中的“-s -S”引數,它會暫停HOT-POT的執行,並等待gdb除錯。
在控制臺中,按“ctrl+shift+t”啟動一個新的控制檯,我們稱之為“除錯控制檯”。在除錯控制臺中,輸入如下命令啟動gdb,準備開始除錯HOT-POT:
cd /hot-pot/dim-sum/
/hot-pot/assistant/gcc-linaro-5.3-2016.02-x86_64_aarch64-elf/bin/aarch64-elf-gdb vmlinux
在(gdb)提示符下,輸入如下命令,連線到qemu:
target remote localhost:1234
您的除錯控制檯看起來是這樣的:
(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x0000000040000000 in ?? ()
在(gdb)提示符下,輸入“c”命令,啟動HOT-POT。然後切換到qemu視窗,看看HOT-POT是不是已經正常啟動了?
接下來,在除錯控制臺中,按“ctrl+c”,暫停HOT-POT的執行,並在(gdb)提示符下,輸入“bt”命令,檢視HOT-POT當前停留在什麼地方?看起來應當是這樣:
(gdb) bt
#0 cpu_do_idle () at arch/arm64/kernel/processor.S:12
#1 0xffffffc0000a8538 in default_powersave () at kernel/sched/idle.c:15
#2 0xffffffc0000a85e8 in default_idle () at kernel/sched/idle.c:27
#3 0xffffffc0000a863c in cpu_idle () at kernel/sched/idle.c:48
#4 0xffffffc0001780c4 in start_master () at init/main.c:96
#5 0x0000000040090240 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
當然了,在除錯控制臺中,您可以使用所有gdb除錯命令。進行諸如單步跟蹤、檢視變數、檢視暫存器、檢視堆疊、切換CPU、彙編單步等等操作。
小問題1.8:在除錯Linux核心時,我無論是用kgdb,還是qemu,發現單步跟蹤時會雜亂無章的跳,有些變數值也看不到。但是HOT-POT中不會這樣,寶友您有什麼竅門?
1.4. 向DIM-SUM作業系統提交補丁
想修改DIM-SUM的程式碼,並把它合入到DIM-SUM的git倉庫嗎?試著給DIM-SUM作業系統提交補丁吧。維護DIM-SUM作業系統的人,使用的都是漢語,溝通起來完全沒有問題。並且他們都不是外星人,您不用覺得他們兇巴巴的:-)
1.4.1. 心態
Paul在《深入理解並行程式設計》一書第11.1.2節中說,驗證和測試工作都需要良好的心態。應當以一種破壞性的、甚至帶一點仇恨的心理來驗證程式碼,有時也應當考慮到:不少人的生命依賴於我們程式碼正確性的機率。總之,心態對事情的成敗有重要的影響。
您在向DIM-SUM提交補丁之前,請保持如下正確的心態:
1、撇開DIM-SUM不談。我們的程式碼,可能會影響不少人的生命,所以為任何專案編寫程式碼,都一定要細心。
2、悲觀的說,如果補丁做得不好,會影響自己的聲譽,並且得不到足夠的關註,最終會導致補丁沒有被採納。
3、樂觀的說,DIM-SUM的維護者、開發者一般都比較Nice,如果你的水平真的比較牛的話。
4、更進一步樂觀的說,您提交的高質量的補丁,可能會為您帶來良好的聲譽、滿意的工作。
如果您和我一樣,有著近乎自大的自信,想要在作業系統方面做出一些成績,請仔細閱讀後面的章節。
1.4.2. 準備工作
躍躍欲試想要提交補丁的讀者,一定已經熟悉Linux開發環境了。在此,作者假設您已經安裝好Linux和git。這裡推薦兩份比較好的git參考資料:
http://git.oschina.net/progit/
https://item.jd.com/11615420.html
1、配置git使用者名稱和郵箱
在配置使用者名稱的時候,建議是“名在前,姓在後”,並且第一個拼音字母大寫。例如我的使用者名稱是:Baoyou Xie。
在配置郵箱時,請使用有意義的郵箱名,而不要用純數字郵箱名。
以下是我的配置:
xiebaoyou@ThinkPad-T440$ git config -l | grep “user”
user.email=baoyou.xie@aliyun.com
user.name=Baoyou Xie
2、配置sendemail
您可以手工修改~/.gitconfig,或者git倉庫下的.git/config檔案,新增[sendemail]節。該配置用於指定傳送補丁時用到的郵件伺服器引數。
以下是我的配置,供參考:
[sendemail]
smtpencryption = tls
smtpserver = smtp.aliyun.com
smtpuser = baoyou.xie@aliyun.com
smtpserverport = 25
配置完成後,請用如下命令,向自己傳送一個測試補丁:
git send-email your.patch –to your.mail –cc your.mail
3、下載原始碼
如果僅僅是為了閱讀本書,而不想向DIM-SUM提交補丁,那麼使用git直接從DIM-SUM主分支拉取程式碼就行了。
使用如下命令可以從主分支拉取DIM-SUM的程式碼:
git clone https://code.csdn.net/xiebaoyou/dim-sum.git
隨時可以使用如下命令更新主分支程式碼:
git fetch origin master
但是,如果想參與到DIM-SUM的開發,那麼就需要從多個git分支拉取程式碼。這是因為:主分支程式碼並不一定是最新的,如果基於這個程式碼製作補丁,很有可能不會順利的合入到Maintainer那裡。換句話說,如果您的程式碼分支沒有與Maintainer保持一致,那麼Maintainer有時會將補丁發回給您,要求您重新製作。所以,一般情況下,您需要再用以下命令,新增其他分支:
git remote add tag-name git-url
其中tag-name是您為分支新增的別名。git-url是DIM-SUM分支的URL路徑。
隨時可以使用如下命令更新分支程式碼:
git fetch tag-name
隨著DIM-SUM的發展,不同的模組會有不同的Maintainer來維護。這些Maintainer會有自己的程式碼分支。可以在DIM-SUM原始碼目錄\MAINTAINERS檔案中,找到相應檔案的維護者,及其git地址。
MAINTAINERS檔案的格式與Linux類似。例如,Linux核心中,watchdog模組的資訊如下:
WATCHDOG DEVICE DRIVERS
M: Wim Van Sebroeck
R: Guenter Roeck
L: linux-watchdog@vger.kernel.org
W: http://www.linux-watchdog.org/
T: git git://www.linux-watchdog.org/linux-watchdog.git
S: Maintained
F: Documentation/devicetree/bindings/watchdog/
F: Documentation/watchdog/
F: drivers/watchdog/
F: include/linux/watchdog.h
F: include/uapi/linux/watchdog.h
其中,git://www.linux-watchdog.org/linux-watchdog.git是其git地址。
4、閱讀Documentation/SubmittingPatches
認真閱讀這個檔案,對正確製作補丁來說很重要。
5、使用如下命令檢出原始碼
git branch mybranch remote-branch
這個命令表示將remote-branch遠端分支作為本地mybranch分支,作為我們工作的基礎。在這個分支上製作補丁,更容易被Maintainer合入。
使用如下命令切換為本地mybranch分支:
git checkout mybranch
接下來,就可以修改原生代碼,開始製作補丁了。
1.4.3. 製作補丁
參與DIM-SUM的開發,可以從簡單的事情入手。例如:
1、消除編譯警告。
2、整理編碼格式,例如註釋裡面的單詞拼寫錯誤、對齊不規範、程式碼格式不符合社群要求。
Linux社群裡面的很多大牛,就是從消除Linux核心警告開始的。下麵我們舉一個簡單的格式整理例子。
在kernel/sched/core.c的第192~193行,其程式碼看起來如下:
192 next = list_first_container(&sched;_runqueue_list[idx],
193 struct task_desc, run_list);
其中第193行有兩個問題:
1、該行包含了84個字元,其中每個TAB鍵佔用8個字元空間,超過了80個字元的限制。
2、與上一行對齊有問題,排版太難看了。
我們刪除該行前面幾個TAB鍵,使其看起來如下:
192 next = list_first_container(&sched;_runqueue_list[idx],
193 struct task_desc, run_list);
修改完成後,在控制檯輸入如下命令將補丁提交到本地git倉庫:
git commit -a
然後使用如下命令生成補丁檔案:
git format-patch -s -v 1 -1
生成的補丁內容如下:
cat v1-0001-.patch
From d75a0cea3945d79176645ce17748aebd5701a07e Mon Sep 17 00:00:00 2001
From: Baoyou Xie
Date: Mon, 21 May 2018 14:29:45 +0800
Subject: [PATCH v1] =?utf-8?q?=E8=B0=83=E5=BA=A6=EF=BC=9A=E6=95=B4?=
=?utf-8?q?=E7=90=86=E4=BB=A3=E7=A0=81=E6=A0=BC=E5=BC=8F?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 8bit
在core.c第193行,程式碼行超過了80個字元,並且與上一行沒有正確的對齊,因此應該刪除其多餘的前導TAB鍵。本補丁刪除這些多餘的TAB鍵以滿足程式碼格式規範。
Signed-off-by: Baoyou Xie
—
kernel/sched/core.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff –git a/kernel/sched/core.c b/kernel/sched/core.c
index 3faa53c..c93df0d 100755
— a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -190,7 +190,7 @@ need_resched:
next = idle_task_desc[smp_processor_id()];
else
next = list_first_container(&sched;_runqueue_list[idx],
–struct task_desc, run_list);
+struct task_desc, run_list);
/**
* 什麼情況下,二者會相等??
—
2.7.4
難道製作一個補丁就這麼簡單?我們可以將它傳送給Maintainer了嗎?
答案當然是否定的。這個補丁有如下問題:
1、沒有徹底解決模組中同類問題。
2、補丁格式不正確。
首先我們應當將補丁回退。使用如下命令進行回退:
git reset HEAD~1
1.4.4. 製作正確的補丁
實際上,在向Maintainer傳送補丁之前,應當用如下對補丁進行檢查:
./scripts/checkpatch.pl your.patch
對於剛才生成的補丁,我們會得到如下錯誤:
WARNING: Possible unwrapped commit description (prefer a maximum 75 chars per line)
#10:
在core.c第193行,程式碼行超過了80個字元,並且與上一行沒有正確的對齊,因此應該刪除其多餘的前導TAB鍵。本補丁刪除這些多餘的TAB鍵以滿足程式碼格式規範。
total: 0 errors, 1 warnings, 8 lines checked
錯誤在於:補丁描述行太長了,應當折行,使每一行低於75個字元。我們再次使用如下命令提交補丁:
git commit -a
在提交的時候,註意修改補丁描述,使其滿足格式規範。反覆製作補丁並使用checkpatch.pl檢查其正確性,直到消除了所有警告為止。當然,極個別的警告是允許存在的。
使用checkpatch.pl僅僅能檢查格式規範方面的錯誤。但是一個正確的補丁遠不止格式正確這麼簡單。它還應該滿足如下要求:
1、一般情況下,同一個補丁只修改同一個模組的程式碼。
如果必須要同時修改多個模組中的程式碼,那麼應該由所有模組的Maintainer同意,並確定由其中某一個Maintainer合入補丁。這種情況僅僅是特例。
但是怎麼確定某個檔案屬於哪一個模組?您應當檢視MAINTAINERS檔案,裡面有一個例子:
核心同步與互斥
M: Baoyou Xie
L: kernel@dim-sum.cn
T: git https://code.csdn.net/xiebaoyou/hot-pot.git core/locking
S: Maintained
F: kernel/locking/
可以看出:kernel/locking目錄下的所有程式碼均屬於“核心同步與互斥”模組。
2、同一個補丁僅僅解決一個獨立的問題。
不要試圖在同一個補丁中解決多個問題。例如,既消除一個編譯警告,又整理一行程式碼。
小問題1.9:但是,消除編譯警告,以及整理程式碼,都僅僅修改了一行程式碼,並且位於同一個檔案之中,也不能將它製作到同一個補丁中?如果不能,請告訴我正確的做法。
3、同一個補丁必須完整的解決一個問題。
換句話說,不能將一個問題分拆到多個補丁中去。正如前一個例子所述,需要在一個補丁中將整個模組的格式全部整理完畢。如果補丁太大,可以考慮每個補丁整理其中一個檔案。
4、補丁不要太大,但這不是一個強制要求遵循的規則。
一般來說,一個補丁修改的程式碼行數,不要超過200行。不過此規則比較靈活。如果一個單獨的問題確實需要修改超過200行程式碼,那麼就突破這個規則吧。
要製作一個正確的補丁,還有一個問題比較重要:補丁的標題和描述。
補丁第一行是標題,它首先應當是模組名稱。
但是我們怎麼找到kernel/sched/core.c檔案屬於哪個模組?
可以試試下麵這個命令,看看kernel/sched/core.c檔案的歷史補丁:
root@ThinkPad-T440:# git log kernel/sched/core.c
commit 0521afdc65cec3265827f68d637ed7d8b07061db
Author: Baoyou Xie
Date: Mon May 21 14:53:49 2018 +0800
排程:整理程式碼格式
在core.c第193行,程式碼行超過了80個字元,並且與上一行
沒有正確的對齊,因此應該刪除其多餘的前導TAB鍵。
本補丁刪除這些多餘的TAB鍵以滿足程式碼格式規範。
可以看到,kernel/sched/core.c檔案所在的模組名稱是“排程”。
其中第一行是標題,在模組名稱後面是補丁標題,應當簡潔,清楚的說明補丁的內容。當然,標題可以超過80個字元。
隨後的內容是補丁描述符,要清楚的描述:
1、為什麼要製作這個補丁
2、這個補丁是如何實現的
當然了,模組的Maintainer可能對補丁描述要額外的要求,您可能也有需要特殊說明的地方,都可以補充在描述中。這有點象寫作文,既要求條理清楚,又沒有成規。
1.4.5. 傳送補丁
在傳送補丁前,我們需要用指令碼再次檢查一下補丁,確保其正確:
./scripts/checkpatch.pl your.patch
如果想要一次性生成併傳送多個補丁,可以使用如下命令生成補丁:
git format-patch -s -v1 HEAD~2
在作者的環境中,上述命令生成了兩個補丁:
v1-0001-DIM-SUM-Good-Start.patch v1-0002-.patch
然後用checkpatch.pl檢查這兩個補丁:
./scripts/checkpatch.pl v1-*.patch
一切無誤,可以使用準備將補丁傳送給Maintainer了🙂
但是應該將補丁發給誰?這可以用get_maintainer.pl來檢視:
root@ThinkPad-T440:# ./scripts/get_maintainer.pl v1-*.patch
“GitAuthor: Baoyou Xie”
接下來,可以用git send-email命令傳送補丁了:
git send-email v1-*.patch –to baoyou.xie@aliyun.com –cc baoyou.xie@aliyun.com
需要註意分辨,哪些人應當作為郵件接收者,哪些人應當作為抄送者。在本例中,補丁是屬於實驗性質的,可以不抄送給郵件串列帳戶。
提醒:您應當將補丁先發給自己,檢查無誤後再發出去。如果你有朋友在Linux社群有較高的威望,有補丁走查的經驗,或者深度參與DIM-SUM的開發,那麼也可以抄送給他,必要的時候,也許他能給您一些幫助。這有助於將補丁順利的合入DIM-SUM。
重要提醒:本章講述的,主要是實驗性質的補丁,用於熟悉提交補丁的流程。真正重要的補丁,可能需要經過反覆修改,才能合入DIM-SUM。並且,這需要您反覆閱讀本書後面章節中,對DIM-SUM內核的程式碼分析。最重要的一點,是需要您對DIM-SUM程式碼的熟練掌握。
1.5. 獲得幫助
如果您在下載原始碼、搭建環境、除錯、提交補丁的過程中,遇到問題,可以透過如下途徑獲得幫助:
1.透過git更新原始碼,並關註根目錄下hot-pot.readme檔案瞭解最新的幫助方式
2.關註“作業系統駭客”公眾號並留言
3.關註作者的部落格:http://blog.chinaunix.net/uid/25845340.html
4.您也可以向baoyou.xie@aliyun.com發郵件來獲得幫助
1.6. 提醒
作者儘量將本書寫得通俗易懂,以方便初學者入門。但是,要真正深入的理解任何一門學問,都需要花費大量的時間,做大量身體力行的練習,並且深入思考。因此,本書會提出一些讓讀者深入思考的小問題。這些小問題值得您在多次閱讀本書後,認真回答。如果您真的想急切知道答案,請閱讀附錄中的答案。但是作者仍然提醒您,不要試圖直接翻閱答案。我閱讀了不少技術書籍,真正優秀的書都註重激發讀者思考的習慣。