主機ubuntu版本: 20.04
qemu模擬處理器:ARM64
Linux內(nèi)核版本:https://www.kernel.org/ 最新版
sudo apt-get install gcc-aarch64-linux-gnu
sudo apt-get install libncurses5-dev build-essential git bison flex libssl-dev
查看版本號
leon@leon:~/work$ aarch64-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=aarch64-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc-cross/aarch64-linux-gnu/9/lto-wrapper
Target: aarch64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 9.3.0-10ubuntu1' --with-bugurl=file:///usr/share/doc/gcc-9/README.Bugs --enable-languages=c,ada,c++,go,d,fortran,objc,obj-c++,gm2 --prefix=/usr --with-gcc-major-version-only --program-suffix=-9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --with-default-libstdcxx-abi=new --enable-gnu-unique-object --disable-libquadmath --disable-libquadmath-support --enable-plugin --enable-default-pie --with-system-zlib --without-target-system-zlib --enable-libpth-m2 --enable-multiarch --enable-fix-cortex-a53-843419 --disable-werror --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=aarch64-linux-gnu --program-prefix=aarch64-linux-gnu- --includedir=/usr/aarch64-linux-gnu/include
Thread model: posix
gcc version 9.3.0 (Ubuntu 9.3.0-10ubuntu1)
sudo apt-get install qemu-system-arm
查看版本:
leon@leon:~/work$ qemu-system-aarch64 --version
QEMU emulator version 4.2.1 (Debian 1:4.2-3ubuntu6.16)
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
leon@leon:~/work$
從源碼安裝
wget https://download.qemu.org/qemu-4.1.0.tar.xz
tar xvJf qemu-4.1.0.tar.xz
cd qemu-4.1.0/
./configure
make -j 8
sudo make install
qemu-system-aarch64 --version
官網(wǎng):http://busybox.net/downloads/下載最新版本即可,這里
tar jxvf busybox-1.33.1.tar.bz2
指定編譯工具
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
打開靜態(tài)庫編譯選項
make menuconfig
Settings --->
[*] Build static binary (no shared libs)
如果報錯:
<command-line>: fatal error: curses.h: No such file or directory
compilation terminated.
安裝ncurses庫
sudo apt-get install libncurses5-dev libncursesw5-dev
PS:編譯過程報錯的話,把相應項去掉即可;
編譯完成,在busybox生成_install目錄
【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【865977150】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。?/blockquote>3.4 補充rootfs目錄結(jié)構(gòu)
(1) 根目錄添加etc、dev和lib目錄
etc目錄:
leon@leon:~/work/Linux/busybox-1.33.1/_install$ ls
bin linuxrc sbin usr
leon@leon:~/work/Linux/busybox-1.33.1/_install$ mkdir etc dev lib
leon@leon:~/work/Linux/busybox-1.33.1/_install$ ls
bin dev etc lib linuxrc sbin usr
leon@leon:~/work/Linux/busybox-1.33.1/_install$在etc分別創(chuàng)建文件:
leon@leon:~/work/Linux/busybox-1.33.1/_install/etc$ cat profile
#!/bin/sh
export HOSTNAME=myQEMU
export USER=root
export HOME=/home
export PS1="[$USER@$HOSTNAME \W]\# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATHleon@leon:~/work/Linux/busybox-1.33.1/_install/etc$ cat fstab
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
debugfs /sys/kernel/debug debugfs defaults 0 0
kmod_mount /mnt 9p trans=virtio 0 0leon@leon:~/work/Linux/busybox-1.33.1/_install/etc$ cat inittab
::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r指定掛載的文件系統(tǒng)
leon@leon:~/work/Linux/busybox-1.33.1/_install/etc/init.d$ cat rcS
mkdir -p /sys
mkdir -p /tmp
mkdir -p /proc
mkdir -p /mnt
/bin/mount -a
mkdir -p /dev/pts
mount -t devpts devpts /dev/pts
echo /sbin/mdev > /proc/sys/kernel/hotplug
mdev -s
leon@leon:~/work/Linux/busybox-1.33.1/_install/etc/init.d$dev目錄:
leon@leon:~/work/Linux/busybox-1.33.1/_install/dev$ sudo mknod console c 5 1
leon@leon:~/work/Linux/busybox-1.33.1/_install/dev$ sudo mknod null c 1 3
leon@leon:~/work/Linux/busybox-1.33.1/_install/dev$lib目錄:拷貝lib庫,支持動態(tài)編譯的應用程序運行
leon@leon:~/work/Linux/busybox-1.33.1/_install/lib$ cp /usr/aarch64-linux-gnu/lib/*.so* -a .
leon@leon:~/work/Linux/busybox-1.33.1/_install/lib$ ls
ld-2.31.so libdl-2.31.so libnsl.so libnss_nisplus-2.31.so libSegFault.so
ld-linux-aarch64.so.1 libdl.so libnsl.so.1 libnss_nisplus.so libstdc++.so.6
libanl-2.31.so libdl.so.2 libnss_compat-2.31.so libnss_nisplus.so.2 libstdc++.so.6.0.28
libanl.so libgcc_s.so.1 libnss_compat.so libnss_nis.so libthread_db-1.0.so
libanl.so.1 libgomp.so.1 libnss_compat.so.2 libnss_nis.so.2 libthread_db.so
libasan.so.5 libgomp.so.1.0.0 libnss_dns-2.31.so libpcprofile.so libthread_db.so.1
libasan.so.5.0.0 libitm.so.1 libnss_dns.so libpthread-2.31.so libtsan.so.0
libatomic.so.1 libitm.so.1.0.0 libnss_dns.so.2 libpthread.so libtsan.so.0.0.0
libatomic.so.1.2.0 liblsan.so.0 libnss_files-2.31.so libpthread.so.0 libubsan.so.1
libBrokenLocale-2.31.so liblsan.so.0.0.0 libnss_files.so libresolv-2.31.so libubsan.so.1.0.0
libBrokenLocale.so libm-2.31.so libnss_files.so.2 libresolv.so libutil-2.31.so
libBrokenLocale.so.1 libmemusage.so libnss_hesiod-2.31.so libresolv.so.2 libutil.so
libc-2.31.so libm.so libnss_hesiod.so librt-2.31.so libutil.so.1
libc.so libm.so.6 libnss_hesiod.so.2 librt.so
libc.so.6 libnsl-2.31.so libnss_nis-2.31.so librt.so.1
leon@leon:~/work/Linux/busybox-1.33.1/_install/lib$step4 編譯內(nèi)核
(1)下載代碼:
#我從torvalds的倉庫fork了一個分支,方便自己添加注釋筆記
git clone https://github.com/luteresa/linux.git(2) 指定編譯工具:
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-配置內(nèi)核:這里采用ARM公司提供的Versatile Express開發(fā)平臺模擬;
sudo cp ../busybox-1.33.1/_install/ ./_install_arm64 -a
cp arch/arm/configs/vexpress_defconfig .config
make menuconfig添加hotplug支持:
Device Drivers
-> Generic Driver Options
-> Support for uevent helper
(/sbin/hotplug) path to uevent helper添加initramfs的支持:
General setup --->
[*]Initial RAM filesystem and RAM disk(initramfs/initrd)
support(_install_arm64) Initramfs souce file(s)內(nèi)核頁分別配置為
Kernel Features --->
Page size(4KB) --->
Virtual address space size(48-bit)--->編譯:
make all -j8
在內(nèi)核根目錄下添加共享目錄
mkdir kmodules
啟動Linux:
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 -kernel arch/arm64/boot/Image --append "rdinit=/linuxrc root=/dev/vda rw console=ttyAMA0 loglevel=8" -nographic --fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount
cpu指定模擬的cpu為 cortex-a57
m 1024 指定內(nèi)存大小為1G
smp4指定模擬的系統(tǒng)為4核處理器
kernel指定啟動的內(nèi)核鏡像
append指定傳遞的命令行參數(shù)
后面的選項指定共享目錄已經(jīng)使用的9P協(xié)議。
如果報類似錯:
qemu-system-aarch64: rom check and register reset failed
大概率是qemu版本問題,換個版本,可以從源碼直接編譯;經(jīng)測試
ubuntu18.04用qemu-4.1.0可以正常工作;
ubuntu20.04用apt安裝即可;wget https://download.qemu.org/qemu-4.1.0.tar.xz
tar xvJf qemu-4.1.0.tar.xz
cd qemu-4.1.0
./configure
make -j 8
編譯完安裝:
sudo make install
默認編譯支持很多個平臺報錯:
mount: mounting debugfs on /sys/kernel/debug failed: No such file or directory
內(nèi)核配置加上CONFIG_DEBUG_FS=y :
Kernel hacking --->
Generic Kernel Debugging Instruments --->
[*] Debug Filesystemstep5: 使用模擬磁盤
上述initramfs的方式,將根文件系統(tǒng)打包到內(nèi)核源碼,運行時都是在內(nèi)存中,可以操作,但系統(tǒng)重啟就會丟失,下面用模擬磁盤方式掛載根文件系統(tǒng)。制作磁盤文件:
dd if=/dev/zero of=rootfs_ext4.img bs=1M count=1024
mkfs.ext4 rootfs_ext4.img
mkdir -p tmpfs
sudo mount -t ext4 rootfs_ext4.img tmpfs/ -o loop
sudo cp -af _install_arm64/* tmpfs/
sudo umount tmpfs
chmod 777 rootfs_ext4.imgrootfs_ext4.img就是即將用來掛載的磁盤,再次啟動內(nèi)核:
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 -kernel arch/arm64/boot/Image --append "noinitrd root=/dev/vda rw console=ttyAMA0 loglevel=8" -nographic -drive if=none,file=rootfs_ext4.img,id=hd0 -device virtio-blk-device,drive=hd0 --fsdev local,id=kmod_dev,path=$PWD/kmodules,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount
傳遞給內(nèi)核的命令行參數(shù)變化了,添加了noinitrd選項,這樣就會掛載我們自己的模擬磁盤。
[root@myQEMU ]# df -mh
Filesystem Size Used Available Use% Mounted on
/dev/root 975.9M 12.8M 895.9M 1% /
tmpfs 496.1M 0 496.1M 0% /tmp
tmpfs 496.1M 0 496.1M 0% /dev
kmod_mount 981.8G 32.5G 899.4G 3% /mnt
[root@myQEMU ]#這樣在文件系統(tǒng)的讀寫,就會存在磁盤,重啟后,數(shù)據(jù)不會丟失。
step6: qemu與主機ubuntu文件共享
前面已經(jīng)支持了主機和qemu上的系統(tǒng)共享目錄,這個目錄就是kmodules目錄:通過mount可以查看被掛載到了qemu上的系統(tǒng)的/mnt目錄下
[root@myQEMU mnt]# mount
/dev/root on / type ext4 (rw,relatime)
proc on /proc type proc (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
kmod_mount on /mnt type 9p (rw,sync,dirsync,relatime,access=client,trans=virtio)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)在ubuntu的kmodules目錄,創(chuàng)建一個文件hello.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello World,Qemu!\n");
return 0;
}在qemu查看
[root@myQEMU mnt]# cat /proc/cpuinfo > cpu.txt
[root@myQEMU mnt]# cat hello.c
#include <stdio.h>
int main(int argc, char **argv)
{
printf("Hello World,Qemu!\n");
return 0;
}
random: fast init done
[root@myQEMU mnt]#在ubuntu編譯
aarch64-linux-gnu-gcc hello.c
在qemu運行
[root@myQEMU mnt]# ./a.out
Hello World,Qemu!
[root@myQEMU mnt]#可見,在共享目錄,可以執(zhí)行含動態(tài)庫的應用程序;
step7:內(nèi)核模塊測試:
Makefile文件
step7:內(nèi)核模塊測試:
Makefile文件,驅(qū)動測試文件module_test.c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/kernel.h>
static int __init module_test_init(void)
{
printk("---module_test_init\n");
return 0;
}
static void __exit module_test_exit(void)
{
printk("---module_test_exit\n");
}
module_init(module_test_init);
module_exit(module_test_exit);
MODULE_LICENSE("GPL");在ubuntu上交叉編譯
leon@leon:~/work/Linux/linux/kmodules$ make
make -C ~/work/Linux/linux M=/home/leon/work/Linux/linux/kmodules modules
make[1]: Entering directory '/home/leon/work/Linux/linux'
CC [M] /home/leon/work/Linux/linux/kmodules/module_test.o
MODPOST /home/leon/work/Linux/linux/kmodules/Module.symvers
CC [M] /home/leon/work/Linux/linux/kmodules/module_test.mod.o
LD [M] /home/leon/work/Linux/linux/kmodules/module_test.ko
make[1]: Leaving directory '/home/leon/work/Linux/linux'
leon@leon:~/work/Linux/linux/kmodules$在qemu加載驅(qū)動
[root@myQEMU mnt]# insmod module_test.ko
---module_test_init.
[root@myQEMU mnt]# rmmod module_test
---module_test_exit.
[root@myQEMU mnt]#可見,內(nèi)核模塊正常運行了。
step8:gdb調(diào)試
安裝arm-none-eabi-gdb
https://askubuntu.com/questions/1243252/how-to-install-arm-none-eabi-gdb-on-ubuntu-20-04-lts-focal-fossasudo apt-get install gdb-multiarch
qemu模擬端啟動內(nèi)核:
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 4 -kernel arch/arm64/boot/Image --append "rdinit=/linuxrc root=/dev/vda rw console=ttyAMA0 loglevel=8" -nographic --fsdev local,id=kmod_dev,path=$PWD/k_shared,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount -S -s
X86啟動gdb:
$ gdb-multiarch --tui vmlinux
(gdb)target remote localhost:1234 //通過1234端口遠程連接到qemu端
(gdb)b start_kernel //在內(nèi)核的start_kernel設置斷點
(gdb)cgdb接管linux內(nèi)核,在斷點處(start_kernel)暫停,即可通過gdb來調(diào)試內(nèi)核。
用Eclipse可視化環(huán)境,單步調(diào)試Linux內(nèi)核
目的:通過可視化環(huán)境,單步調(diào)試linux內(nèi)核
開發(fā)環(huán)境:ubuntu20.04安裝java環(huán)境
Eclipse運行依賴jave環(huán)境;
sudo apt install openjdk-13-jre
安裝Eclipse-CDT
官網(wǎng):http://www.eclipse.org/cdt/
配置Eclipse-CDT
(1)創(chuàng)建工程
在Eclipse菜單選擇File->New->Project,選擇Makefile Project with Exiting Code,即可創(chuàng)建一個新工程;
(2)配置調(diào)選項
選擇Eclipse菜單中的Run->Debug Configurations, 彈出Debug configurations
(3)debugger選項卡,配置
Debugger:gdbserver
GDB debugger:gdb-multiarch進行單步調(diào)試Linux內(nèi)核
主機端運行qemu仿真系統(tǒng)
qemu-system-aarch64 -machine virt -cpu cortex-a57 -machine type=virt -m 1024 -smp 1 -kernel arch/arm64/boot/Image --append "rdinit=/linuxrc root=/dev/vda rw console=ttyAMA0 loglevel=8" -nographic --fsdev local,id=kmod_dev,path=$PWD/k_shared,security_model=none -device virtio-9p-device,fsdev=kmod_dev,mount_tag=kmod_mount -S -s
啟動Eclipse,選擇Run->Debug History, 在Debugger Console選項卡輸入file vmlinux導入調(diào)試文件的符號表;輸入set architecture aarch64命令,設定GDB支持ARM64架構(gòu):
配置完成,便可在Eclipse可視化環(huán)境,進行l(wèi)inux內(nèi)核單步調(diào)試;
Eclipse比GDB命令直觀很多,可以方便查看參數(shù),局部變量,寄存器值等;
聯(lián)系客服