Linux内核学习:在QEMU上运行一个能够挂载Ext4文件的Linux内核

目录

0 写在前面的话

1 QEMU调试Linux内核

1.1 准备依赖包

1.2 编译最小文件系统

1.3 编译内核

1.4 运行QEMU上的linux 5.0内核

2 挂载一个ext4文件目录到Linux 5.0内核上

2.1 创建ext4文件系统分区

2.2 重新编译内核

2.3 挂载磁盘目录

2.4 共享主机文件


0 写在前面的话

最近在学习Linux内核的一些相关知识,所以在这里做个记录。

一开始在想的问题是,既然我们要写Linux内核,那么我们怎么去调试它呢,如果我们本机是一个Linux,那么无论是我们编写内核模块,还是调试内核代码,只要一出现bug,必然整个Linux OS就死了啊,所以这个问题该怎么解决呢?查了好多资料才知道,一般情况下,为了加速开发过程,可以选择Versatile Express平台进行产品原型开发,作为个人学习使用的话,没有必要购买开发平台或者ARM开发版,完全可以用QEMU来模拟开发平台。所以我们任务的第一步就明确了,通过QEMU运行一个最简单的可以Linux内核系统。

1 QEMU调试Linux内核

1.1 准备依赖包

首先可以选择一台Ubuntu16.04或者Ubuntu18.04的实体物理机,或者虚拟机来进行实验。但虚拟机必须支持嵌套虚拟化,具体可以通过VMware的操作协议进行操作。

在Ubuntu中安装如下工具,我使用的环境是Ubuntu18.04的实体物理机:

sudo apt-get install qemu libncurses5-dev gcc-arm-linux-gnueabi build-essential

下载代码包:

linux-5.0 内核:

wget https://www.kernel.org/pub/linux/kernel/v5.x/linux-5.0.tar.gz

busybox工具包:

wget https://busybox.net/downloads/busybox-1.30.0.tar.bz2

1.2 编译最小文件系统

利用Busybox手动编译一个最小文件系统:

cd busybox
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make menuconfig

进入menuconfig后,配置成静态编译:

Busybox Settings ---->Build Options ----> Build BusyBox as a static binary. (No shared library)
选择完成后:
make
make install

之后在busybox的根目录会生成一个 _install 文件夹,该目录是编译好的文件系统需要的一些命令集合。

把_install 目录放到linux-5.0目录下。

进入linux-5.0/_install下:

mkdir etc dev mnt
mkdir -p /etc/init.d/
vim _install/etc/init.d/rcS

新建一个rcS文件,然后在文件中添加如下内容:

mkdir -p /proc
mkdir -p /tmp
mkdir -p /sys
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

如果当前在root用户上就不用进行文件权限赋予操作,如果不是

需要给rcS赋予权限:

chmod +x rcS

在_install/etc中创建fstab文件,并写入内容,这个文件主要写的是文件挂载的内容:

proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0

在_install/etc中创建inittab文件,写入如下内容,这个文件写入的是一些控制命令操作的信息:

::sysinit:/etc/init.d/rcS
::respawn:-/bin/sh
::askfirst:-/bin/sh
::ctrlaltdel:/bin/umount -a -r

在_install/dev中创建设备节点:

cd _install/dev/
mknod console c 5 1
mknod null c 1 3

1.3 编译内核

cd linux-5.0
export ARCH=arm
export CROSS_COMPILE=arm-linux-gnueabi-
make menuconfig

配置initarmfs:

General setup ---> Initial RAM filesystem and RAM disk(initramfs/initrd) support
    (_install)Initramfs source file(s)
Boot Options --->
    ()Default kernel command String
Kernel Features --->
    Memory Split(3G/1G user/kernel split)
    [*]High Memory Support

开始编译:

make bzImage -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make dtbs

1.4 运行QEMU上的linux 5.0内核

qemu-system-arm -M vexpress-a9 -smp 4 -m 1024M -kernel arch/arm/boot/zImage -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic 

运行结果如下:

pulseaudio: pa_context_connect() failed
pulseaudio: Reason: Connection refused
pulseaudio: Failed to initialize PA contextaudio: Could not init `pa' audio driver
Booting Linux on physical CPU 0x0
Linux version 5.0.0 (root@pc) (gcc version 7.4.0 (Ubuntu/Linaro 7.4.0-1ubuntu1~18.04.1)) #3 SMP Mon Dec 2 23:28:59 UTC 2019
CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7), cr=10c5387d
CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache
OF: fdt: Machine model: V2P-CA9
Memory policy: Data cache writealloc
Reserved memory: created DMA memory pool at 0x4c000000, size 8 MiB
OF: reserved mem: initialized node vram@4c000000, compatible id shared-dma-pool
cma: Reserved 16 MiB at 0x9f000000
On node 0 totalpages: 262144
  Normal zone: 1536 pages used for memmap
  Normal zone: 0 pages reserved
  Normal zone: 196608 pages, LIFO batch:63
  HighMem zone: 65536 pages, LIFO batch:15
random: get_random_bytes called from start_kernel+0xa0/0x45c with crng_init=0
percpu: Embedded 17 pages/cpu @(ptrval) s37260 r8192 d24180 u69632
pcpu-alloc: s37260 r8192 d24180 u69632 alloc=17*4096
pcpu-alloc: [0] 0 [0] 1 [0] 2 [0] 3 
Built 1 zonelists, mobility grouping on.  Total pages: 260608
Kernel command line: rdinit=/linuxrc console=ttyAMA0 loglevel=8
printk: log_buf_len individual max cpu contribution: 4096 bytes
printk: log_buf_len total cpu_extra contributions: 12288 bytes
printk: log_buf_len min size: 16384 bytes
printk: log_buf_len: 32768 bytes
printk: early log buf free: 14736(89%)
Dentry cache hash table entries: 131072 (order: 7, 524288 bytes)
Inode-cache hash table entries: 65536 (order: 6, 262144 bytes)
Memory: 1010936K/1048576K available (7168K kernel code, 421K rwdata, 1572K rodata, 2048K init, 176K bss, 21256K reserved, 16384K cma-reserved, 245760K highmem)
Virtual kernel memory layout:
    vector  : 0xffff0000 - 0xffff1000   (   4 kB)
    fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
    vmalloc : 0xf0800000 - 0xff800000   ( 240 MB)
    lowmem  : 0xc0000000 - 0xf0000000   ( 768 MB)
    pkmap   : 0xbfe00000 - 0xc0000000   (   2 MB)
    modules : 0xbf000000 - 0xbfe00000   (  14 MB)
      .text : 0x(ptrval) - 0x(ptrval)   (8160 kB)
      .init : 0x(ptrval) - 0x(ptrval)   (2048 kB)
      .data : 0x(ptrval) - 0x(ptrval)   ( 422 kB)
       .bss : 0x(ptrval) - 0x(ptrval)   ( 177 kB)
SLUB: HWalign=64, Order=0-3, MinObjects=0, CPUs=4, Nodes=1
rcu: Hierarchical RCU implementation.
rcu:    RCU event tracing is enabled.
rcu:    RCU restricting CPUs from NR_CPUS=8 to nr_cpu_ids=4.
rcu: RCU calculated value of scheduler-enlistment delay is 10 jiffies.
rcu: Adjusting geometry for rcu_fanout_leaf=16, nr_cpu_ids=4
NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
L2C: platform modifies aux control register: 0x02020000 -> 0x02420000
L2C: DT/platform modifies aux control register: 0x02020000 -> 0x02420000
L2C-310 enabling early BRESP for Cortex-A9
L2C-310 full line of zeros enabled for Cortex-A9
L2C-310 dynamic clock gating disabled, standby mode disabled
L2C-310 cache controller enabled, 8 ways, 128 kB
L2C-310: CACHE_ID 0x410000c8, AUX_CTRL 0x46420001
sched_clock: 32 bits at 24MHz, resolution 41ns, wraps every 89478484971ns
clocksource: arm,sp804: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 1911260446275 ns
Failed to initialize '/smb@4000000/motherboard/iofpga@7,00000000/timer@12000': -22
smp_twd: clock not found -2
Console: colour dummy device 80x30
Calibrating local timer... 99.98MHz.
Calibrating delay loop... 430.08 BogoMIPS (lpj=2150400)
pid_max: default: 32768 minimum: 301
Mount-cache hash table entries: 2048 (order: 1, 8192 bytes)
Mountpoint-cache hash table entries: 2048 (order: 1, 8192 bytes)
CPU: Testing write buffer coherency: ok
CPU0: Spectre v2: using BPIALL workaround
CPU0: thread -1, cpu 0, socket 0, mpidr 80000000
Setting up static identity map for 0x60100000 - 0x60100060
rcu: Hierarchical SRCU implementation.
smp: Bringing up secondary CPUs ...
CPU1: thread -1, cpu 1, socket 0, mpidr 80000001
CPU1: Spectre v2: using BPIALL workaround
CPU2: thread -1, cpu 2, socket 0, mpidr 80000002
CPU2: Spectre v2: using BPIALL workaround
CPU3: thread -1, cpu 3, socket 0, mpidr 80000003
CPU3: Spectre v2: using BPIALL workaround
smp: Brought up 1 node, 4 CPUs
SMP: Total of 4 processors activated (1787.90 BogoMIPS).
CPU: All CPU(s) started in SVC mode.
devtmpfs: initialized
VFP support v0.3: implementor 41 architecture 3 part 30 variant 9 rev 0
clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
futex hash table entries: 1024 (order: 4, 65536 bytes)
NET: Registered protocol family 16
DMA: preallocated 256 KiB pool for atomic coherent allocations
cpuidle: using governor ladder
hw-breakpoint: debug architecture 0x4 unsupported.
Serial: AMBA PL011 UART driver
10009000.uart: ttyAMA0 at MMIO 0x10009000 (irq = 29, base_baud = 0) is a PL011 rev1
printk: console [ttyAMA0] enabled
1000a000.uart: ttyAMA1 at MMIO 0x1000a000 (irq = 30, base_baud = 0) is a PL011 rev1
1000b000.uart: ttyAMA2 at MMIO 0x1000b000 (irq = 31, base_baud = 0) is a PL011 rev1
1000c000.uart: ttyAMA3 at MMIO 0x1000c000 (irq = 32, base_baud = 0) is a PL011 rev1
OF: amba_device_add() failed (-19) for /smb@4000000/motherboard/iofpga@7,00000000/wdt@f000
OF: amba_device_add() failed (-19) for /memory-controller@100e0000
OF: amba_device_add() failed (-19) for /memory-controller@100e1000
OF: amba_device_add() failed (-19) for /watchdog@100e5000
irq: type mismatch, failed to map hwirq-75 for interrupt-controller@1e001000!
SCSI subsystem initialized
libata version 3.00 loaded.
usbcore: registered new interface driver usbfs
usbcore: registered new interface driver hub
usbcore: registered new device driver usb
Advanced Linux Sound Architecture Driver Initialized.
clocksource: Switched to clocksource arm,sp804
NET: Registered protocol family 2
tcp_listen_portaddr_hash hash table entries: 512 (order: 0, 6144 bytes)
TCP established hash table entries: 8192 (order: 3, 32768 bytes)
TCP bind hash table entries: 8192 (order: 4, 65536 bytes)
TCP: Hash tables configured (established 8192 bind 8192)
UDP hash table entries: 512 (order: 2, 16384 bytes)
UDP-Lite hash table entries: 512 (order: 2, 16384 bytes)
NET: Registered protocol family 1
RPC: Registered named UNIX socket transport module.
RPC: Registered udp transport module.
RPC: Registered tcp transport module.
RPC: Registered tcp NFSv4.1 backchannel transport module.
hw perfevents: enabled with armv7_cortex_a9 PMU driver, 1 counters available
workingset: timestamp_bits=30 max_order=18 bucket_order=0
squashfs: version 4.0 (2009/01/31) Phillip Lougher
jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
9p: Installing v9fs 9p2000 file system support
bounce: pool size: 64 pages
io scheduler mq-deadline registered
io scheduler kyber registered
drm-clcd-pl111 1001f000.clcd: assigned reserved memory node vram@4c000000
drm-clcd-pl111 1001f000.clcd: using device-specific reserved memory
drm-clcd-pl111 1001f000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 1001f000.clcd: core tile graphics present
drm-clcd-pl111 1001f000.clcd: this device will be deactivated
Error: Driver 'vexpress-muxfpga' is already registered, aborting...
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x40000000-0x43ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
erase region 0: offset=0x0,size=0x40000,blocks=256
physmap-flash 40000000.flash: physmap platform flash device: [mem 0x44000000-0x47ffffff]
40000000.flash: Found 2 x16 devices at 0x0 in 32-bit bank. Manufacturer ID 0x000000 Chip ID 0x000000
Intel/Sharp Extended Query Table at 0x0031
Using buffer write method
erase region 0: offset=0x0,size=0x40000,blocks=256
Concatenating MTD devices:
(0): "40000000.flash"
(1): "40000000.flash"
into device "40000000.flash"
physmap-flash 48000000.psram: physmap platform flash device: [mem 0x48000000-0x49ffffff]
libphy: Fixed MDIO Bus: probed
smsc911x 4e000000.ethernet: Linked as a consumer to regulator.1
libphy: smsc911x-mdio: probed
smsc911x 4e000000.ethernet eth0: MAC Address: 52:54:00:12:34:56
isp1760 4f000000.usb: bus width: 32, oc: digital
isp1760 4f000000.usb: NXP ISP1760 USB Host Controller
isp1760 4f000000.usb: new USB bus registered, assigned bus number 1
isp1760 4f000000.usb: Scratch test failed.
isp1760 4f000000.usb: can't setup: -19
isp1760 4f000000.usb: USB bus 1 deregistered
rtc-pl031 10017000.rtc: registered as rtc0
mmci-pl18x 10005000.mmci: Got CD GPIO
mmci-pl18x 10005000.mmci: Got WP GPIO
mmci-pl18x 10005000.mmci: Linked as a consumer to regulator.1
mmci-pl18x 10005000.mmci: mmc0: PL181 manf 41 rev0 at 0x10005000 irq 25,26 (pio)
ledtrig-cpu: registered to indicate activity on CPUs
usbcore: registered new interface driver usbhid
usbhid: USB HID core driver
aaci-pl041 10004000.aaci: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 24
aaci-pl041 10004000.aaci: FIFO 512 entries
oprofile: using arm/armv7-ca9
NET: Registered protocol family 17
9pnet: Installing 9P2000 support
Registering SWP/SWPB emulation handler
input: AT Raw Set 2 keyboard as /devices/platform/smb@4000000/smb@4000000:motherboard/smb@4000000:motherboard:iofpga@7,00000000/10006000.kmi/serio0/input/input0
Error: Driver 'vexpress-muxfpga' is already registered, aborting...
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
Error: Driver 'vexpress-muxfpga' is already registered, aborting...
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
rtc-pl031 10017000.rtc: setting system clock to 2019-12-03T10:34:18 UTC (1575369258)
ALSA device list:
  #0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 24
Freeing unused kernel memory: 2048K
Run /linuxrc as init process
input: ImExPS/2 Generic Explorer Mouse as /devices/platform/smb@4000000/smb@4000000:motherboard/smb@4000000:motherboard:iofpga@7,00000000/10007000.kmi/serio1/input/input2
Error: Driver 'vexpress-muxfpga' is already registered, aborting...
drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD

Please press Enter to activate this console. 

/ # ls
bin      etc      mnt      sbin     tmp
dev      linuxrc  proc     sys      usr

可以看到启动成功了一个Linux内核系统。

2 挂载一个ext4文件目录到Linux 5.0内核上

这么做的目的是为了更好的调试内核,无论是写内核模块还是调试代码,都要有一个文件系统,能够让本机和QEMU运行的linux5.0内核能够文件共享,这样写好的内核可以放到Linux 5.0内核中去调试。

所以现在的目的就是要挂载一个ext4格式的文件磁盘,并把它挂载到我们的内核上:

2.1 创建ext4文件系统分区

dd if=/dev/zero of=ext4.img bs=512 count=131072
mkfs.ext4 ext4.img

挂载ext4文件系统要设置一下config文件内容:

vim linux-5.0/.config
设置下面内容
CONFIG_LBDAF=y
CONFIG_EXT4_FS=y

2.2 重新编译内核

make vexpress_defconfig
make bzImage -j4 ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
make dtbs

 再次运行QEMU:

​qemu-system-arm -M vexpress-a9 -smp 4 \
 -m 1024M \
 -kernel arch/arm/boot/zImage \
 -append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" \
 -dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb  \
 -nographic \
 -sd ext4.img

2.3 挂载磁盘目录

mount -t ext4 /dev/mmcblk0 /mnt/

2.4 共享主机文件

在主机目录上新建workspace目录,然后将磁盘挂载在该目录,实现了和QEMU中Linux内核的文件共享:

mkdir workspace
mount ext4.img workspace

 

你可能感兴趣的:(Linux内核,计算机系统结构)