2019-5-3
主要內容摘自 孟寧《庖丁解牛Linux內核分析》
天下大事必作於細,天下難事必作於易
1.計算機三大法寶
- 存儲程序計算機
- 函數調用堆棧
- 中斷
2.虛擬一個x86的CPU硬件平台
2.1 虛擬環境搭建
sudo apt-get install qemu # 安裝qemu
sudo ln -s /usr/bin/qemu-system-i386 /usr/bin/qemu # 生成qemu-system-i386的符號鏈接qemu
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.9.4.tar.xz # 下載linux-3.9.4.tar.xz
# 下載mykernel補丁
wget https://www.raw.github.com/mengning/mykernel/master/mykernel_for_linux3.9.4sc.patch
xz -d linux-3.9.4.tar.xz
tar -xvf linux-3.9.4.tar
cd linux-3.9.4
patch -p1 < ../mykernel_for_linux3.9.4sc.patch # 添加補丁,注意參數為p1不是pl
make allnoconfig
make # 編譯mykernel
qemu -kernel arch/x86/boot/bzImage
2.2使用mykernel編寫時間片輪轉多道程序內核
1.mykernel相關文件
- mypcb.h
- mymain.c
- myinterrupt.c
2.使用gdb調試內核
gdb # 運行gdb
# 在gdb程序中,輸入:
file linux3.9.4/vmlinux # 加載符號表
target remote:1234 # 建立連接
break start_kernel # 插入斷點
3.MenuOS的構造
3.1 Linux內核源代碼簡介
操作系統兩把“寶劍”
- 中斷上下文
- 進程上下文
使用版本:linux-3.18.6
內核分析中重要的文件:
- arch/x86
- init/main.c
- kernel
linux readme
- what is linux?
- on what hardware does it run?
- documentation
- installing the kernel source
- software requirements
- build directory for the kernel
- configuring the kernel
- compiling the kernel
- if something goes wrong
- 編譯安裝內核大概步驟
(1) 安裝開發包組
(2) 下載源碼文件
(3) .config:准備內核選項
(4) make menuconfig:配置內核選項
(5) make [-j #]
(6) make modules_install:安裝模塊
(7) make install:安裝內核相關文件
(8) 安裝bzImage為/boot/vmlinuz-VERSION_RELEASE
(9) 生成initramfs文件
(10) 編輯grub的配置文件
2.編譯配置選項
(1) 配置內核選項
(2) 支持“更新”模式進行配置:make help
- make config:在命令行中以遍歷的方式去配置內核中可配置的每一個選項。
- make menuconfig:基於curses的文本窗口界面
- make gconfig:基於GTK(GNOME)環境窗口界面
- make xconfig:基於QT(KDE)環境的窗口界面
(3) 支持“全新配置”模式進行配置 - make defconfig:基於內核為目標平台提供的默認配置進行配置
- make allyesconfig:所有選項回答為"yes"
- make allnoconfig:所有選項回答為"no"
3.編譯
make [-j #] : 全部編譯
3.2 構造一個簡單的Linux內核
編譯、運行、跟蹤源代碼
MenuOS:由Linux內核和該文件系統集成
qemu -kernel linux-3.18.6/arch/x86/boot/bzImage -initrd rootfs.img
解釋
qemu: 仿真kernel的虛擬機;
bzImage:vmLinux經過gzip壓縮后的文件,是壓縮的內核映像,'b'表示'big'(bzImage適用於大內核,zImage適用於小內核);
vmLinux:編譯出來的最原始的內核ELF文件;
根文件系統:一般包含內存根文件和磁盤文件系統
initrd:是“initial ramdisk”簡寫,普通用戶一般感受不到這個內存根文件系統的存在,因為普通Linux在啟動時,是boot loader將存儲介質中的initrd文件加載到內存,內核啟動時先訪問initrd文件系統(內存根文件系統),然后再切換到磁盤文件系統。為簡化實驗只使用了initrd根文件系統
(1)下載內核源代碼並解壓
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.18.6.tar.xz
xz -d linux-3.18.6.tar.xz
tar -xvf linux-3.18.6.tar
cd linux-3.18.6
make i386_defconfig
make
(2)制作根文件系統(返回上級目錄)
mkdir rootfs
git clone https:/github.com/mengning/menu.git
cd menu
gcc pthread -o init linkable.c menu.c test.c -m32 -static
cd ../rootfs
cp ../menu/init ./ # 將init復制到rootfs下
find . | cpio -o -Hnewc | gzip -9 > ../rootfs.img # 把當前rootfs下的所有文件打包成一個鏡像文件
配置內核編譯選項出現的問題
zgd@zgd-ThinkPad-X260:~/kernel/linux-3.18.6$ make menuconfig
HOSTLD scripts/kconfig/mconf
/usr/bin/ld: scripts/kconfig/zconf.tab.o: relocation R_X86_64_32 against `.rodata.str1.1' can not be used when making a PIE object; recompile with -fPIC
/usr/bin/ld: final link failed: Nonrepresentable section on output
collect2: error: ld returned 1 exit status
scripts/Makefile.host:100: recipe for target 'scripts/kconfig/mconf' failed
make[1]: *** [scripts/kconfig/mconf] Error 1
Makefile:541: recipe for target 'menuconfig' failed
make: *** [menuconfig] Error 2
原因及解決方法
原因:gcc版本太高,ubuntu18自帶gcc版本為7.4,高版本gcc默認開啟-fPIC(Position independent code)支持動態庫的重定位
方法:安裝gcc-4.8,生成新的/usr/bin/gcc鏈接,重新配置menuconfig再編譯即可