常常有人問一臺機器如何將hello經網絡發送給另外一臺機器,我確實是不知道,只能看代碼了。
說明:本人對內核的研究學習也是剛剛起步,有不少不了解的,因此文中可能會有一些「一本正經的胡扯」。請你們辯證的閱讀。注意這種方式不能調試 start_kernel等過程,我主要用來調試tcp/ip協議棧代碼。若是想調試start_kernel,後面會介紹用qemu的方式。java
S1. 開發機:我是將一個老的索尼的筆記本裝了Ubuntu桌面版本做爲開發環境,版本號是Ubuntu 16.04.4 LTS,後面在某些步驟中也會稱之爲host。
S2. JDK使用的是java version "1.7.0_80"。 官網也有下載。後面CDT開發工具要用。
S3. Eclipse版本 Mars.2 Release (4.5.2),CDT(8.8.1)使用的插件的方式安裝的。 相關軟件在eclipse官網都可以得到。至於怎麼裝插件,請網上搜索。
S4. Virtualbox,版本 5.2.18 r124319 (Qt5.6.1)。 官網下載的linux版本。
S5. 開發機安裝socat,模擬串口通訊用。sudo apt-get install socat
S6. 開發機安裝build工具鏈。linux
sudo apt-get install gcc sudo apt-get install build-essential
S7. Virtualbox新建ubuntu虛擬機做爲調試目標機,安裝的虛擬機的系統用的鏡像是:ubuntu-16.04-server-amd64.iso。至於怎麼用virtualbox裝虛擬機,請網上搜索。
虛擬機的CPU請根據你實際機器CPU的數量選擇,我選擇的是2,後面會對編譯速度的提高有幫助。
虛擬機的網卡設置: 選中你的virtualbox虛擬機-->設置-->網絡-->網卡1-->勾上 啓用網絡鏈接/鏈接方式 選擇 橋接網卡/界面名稱 選擇 你能聯網的網卡。
。
虛擬機串口設置: 選中你的virtualbox虛擬機-->設置-->串口-->端口1-->勾上 啓用串口/端口模式 選擇 主機管道/路徑地址填寫 /tmp/s
git
安裝時,有個注意事項,語言選擇English,不然可能會出現安裝出錯。另,安裝server工具步驟時建議選擇上openssh server。選擇須要安裝grub做爲磁盤引導器。後面我麼會稱這臺裝好的虛擬機爲guest機器,或者調試目標機,或者調試機,或者target等等。github
S8. 登陸到調試目標機,準備內核代碼。
到內核官網下載你要用的內核,個人用的是[4.4.19]版本(https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.4.19.tar.gz)。能夠用wget xxx內核連接地址的辦法下載,個人是:shell
cd ~ mkdir 004.code cd 004.code wget https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/linux-4.4.19.tar.gz tar -xzvf linux-4.4.19.tar.gz cd linux-4.4.19
S9. 在調試目標機準備編譯安裝內核。
修改Makefile文件(linux-4.4.19目錄下),將其中的O2字樣修改爲O1,目前不支持O0編譯。可是有個文章說能夠經過修改內核代碼達到使用O0編譯的目的。我試了試,沒成功。若是誰成功了,能夠告訴我,謝謝。
安裝必要的依賴:ubuntu
sudo apt-get install libncurses5-dev sudo apt-get install libssl-dev sudo apt-get install bc
調試目標機安裝build工具鏈。網絡
sudo apt-get install gcc sudo apt-get install build-essential
配置內核選項,其實只須要執行這步生成config文件,配置項不用修改,咱們要的都有。app
make menuconfig
而後選擇 exit 而後選擇yes 生成config文件。eclipse
make CONFIG_DEBUG_SECTION_MISMATCH=y -j2
此步驟須要很長時間,2-5小時不等,正常能夠在睡覺前執行,次日早上起來看結果。ssh
S10. 在調試目標機安裝新編譯的內核。
工做目錄在linux-4.4.19
sudo make modules_install sudo make install
S11. 在調試目標機修改啓動引導選項。
在第10步完成後重啓機器時,在啓動菜單中選擇Advance...菜單中,能夠看到新安裝的4.4.19內核的引導項。
進入系統(用4.4.19 或者以前的默認內核均可以),修改啓動引導配置文件。
cd /boot/grub sudo su - root cp grub.cfg grub.cfg.bk.180917 chmod +w grub.cfg vi grub.cfg
找到menuentry 'Ubuntu, with Linux 4.4.19......這個地方,爲了便於識別,能夠講此處單引號內的4.4.19後面加上-debug-kernel字樣(可選)。 從這行開始向下查看,找到最挨着的linux /vmlinuz-4.4.19 root=...ro 這一行,在 這一行後面加上kgdb=ttyS0 kgdboc=ttyS0,115200 kgdbwait
S12. 在調試目標機將代碼和編譯產物拷貝給開發機。我用的scp,你能夠選擇ftp等方式。
scp -r linux-4.4.19 simon@192.168.2.7:/home/simon/004.code/linux-4.4.19
用戶名 ip 路徑 根據你本身實際狀況肯定。不明白的能夠搜搜scp命令怎麼用,再不行就用ftp的方式搞。 也有人經過虛擬機共享目錄的方式搞,這個不重要,你能拿到開發機上面就行。
S13. 在開發機,配置CDT並準備工程。
打開裝了CDT插件的eclipse。
window-->preferences-->General-->Workspace 去掉勾選 Build Automatically。
window-->preferences-->C/C++-->indexer 去掉勾選 Enable indexer。
file-->new-->c project-->project name填寫你本身合意的,好比linux-kernel-study / 去掉use default location,location輸入框中選擇你的linux-4.4.19路徑。 / project type 選擇 Makefile project-Empty project / Toolschains選擇Linux GCC-->next-->Advanced Setting-->C/C++ Build-->去掉勾選use default build command, build command輸入框內寫上 make CONFIG_DEBUG_SECTION_MISMATCH=y -j2,build directory選擇你的linux-4.4.19路徑。 / Behavior頁籤 Build(Increament build) 輸入框中輸入一個空格便可。而後完成工程建立便可。
點擊工具欄中的綠色小蟲子右邊的箭頭,選擇Debug Configurations-->C/C++ Remote Application(雙擊)-->proiect選擇你剛建立的project / C/C++ Application選擇你的linux-4.4.19路徑下的vmlinux。 / 選中 Disable auto build 點擊select other換一個啓動器 選擇 GDB(DSF)Manual Remote Debugging...
點擊debugger頁籤 點擊connection子頁籤,type選擇Serial, speed選擇115200,dev後面再來填。此處標誌爲待填13.1。
點擊apply close便可。
S14. 啓動調試目標機,在啓動菜單處,選擇 advance.../Ubuntu, with Linux 4.4.19-debuge-kernel這個內核引導項目。
在開發機執行命令:socat -d -d /tmp/s pty
他會有個輸出 /dev/pts/.. 把這個路徑填到13步待填13.1處。
cd 你的linux-4.4.19路徑
gdb vmlinux
target remote /dev/pts/.. (此處對應上面的輸出,不是真的寫一個..)
此時就應該鏈接上目標機器了。按gdb的c指令即可以使得調試目標機繼續啓動下去。
若是須要加設斷點等,能夠在調試目標機執行
sudo su - root
echo g > /proc/sysrq-trigger
這樣目標機就會暫停,能夠在開發機中加設斷點。
注意這種方式不能調試 start_kernel等過程,我主要用來調試tcp/ip協議棧代碼。
S15. 在開發機用CDT調試。
退掉14步的gdb調試。
在調試目標機執行 sudo echo g > /proc/sysrq-trigger
點擊CDT工具欄中的綠色小蟲子右邊的箭頭,選擇1New_configuration,若是有什麼錯誤提示不用理會,繼續proceed。 鏈接成功後,控制檯會有輸出,好比咱們能夠在控制檯輸入 b af_inet.c:471 而後輸入gdb 指令 c
而後 在目標機執行 nc -l 8080
而後你就能夠發現斷點停在了 snum = ntohs(addr->sin_port);, 這個時候你就能夠調試server的bind動做了,其餘諸如listen accept connect等相似方式調試。
F5 F6這些快捷鍵均可以用,只是你每次增減斷點,貌似都要如今目標機執行 echo g > /proc/sysrq-trigger,使他先停下來,纔好加斷點等操做。