• 记录QEMU上模拟ARM运行环境(内核 2.6.30)


    下载安装包

    # gnu-gcc交叉编译链
    sudo apt-get install gcc-arm-linux-gnueabi
    # qume
    sudo apt-get install qemu-system-arm
    # Linux 2.6.30.4
    wget https://mirrors.edge.kernel.org/pub/linux/kernel/v2.6/linux-2.6.30.4.tar.gz
    # busybox-1.28.4
    wget https://busybox.net/downloads/busybox-1.28.4.tar.bz2
    # 其他环境
    apt-get -y install g++-arm-linux-gnueabihf libexpat1-dev libncurses5-dev
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    注意Linuxgcc版本匹配支持!

    root@huawei linux-2.6.30.4 # find . -name "compiler-gcc*"                                                                                                                                                 [130]
    ./include/linux/compiler-gcc4.h
    ./include/linux/compiler-gcc.h
    ./include/linux/compiler-gcc3.h
    
    • 1
    • 2
    • 3
    • 4

    运行环境

    Linux huawei 5.4.0-100-generic #113-Ubuntu SMP Thu Feb 3 18:43:29 UTC 2022 x86_64 x86_64 x86_64 GNU/Linux
    
    • 1

    设备平台:

    • 操作系统:Ubuntu
    • 内核版本:5.4.0-100-generic
    • 架构:x86_64

    新建目录qume-linux

    mkdir qume-linux
    cd ./qume-linux
    tar -xzvf linux-2.6.30.4.tar.gz
    
    • 1
    • 2
    • 3

    编译最小根文件系统

    tar -jxvf busybox-1.28.4.tar.bz2
    cd busybox-1.28.4
    export ARCH=arm
    export CROSS_COMPILE=arm-linux-gnueabi-
    # 此处要安装图形库
    make menuconfig  # 选择Setting->Build Options [*]Build static binary(no shared libs)
    make install  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    完成后会在目录中生成_install目录,本目录存放了编译好的文件系统需要的命令集合

    此处有两种方法可以生成最小根文件系统,一种是使用虚拟内存文件系统,一种是直接新建物理节点(可见参考链接部分),下面 主要介绍使用虚拟内存文件系统

    第一个方法

    mkdir boot_demo
    cd ./boot_demo
    # 把busybox中的busybox文件复制到一个新的目录
    cp -r /root/test_linux/busybox-1.35.0/_install/bin/busybox  ./busybox
    mkdir initramfs
    cd ./initramfs/
    mkdir bin
    mv ../busybox  .
    mv ./busybox   ./bin/
    vim init
    chmod  +x init
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    其中init文件

    #!/bin/busybox sh
    
    /bin/busybox echo "Hello Linux"
    
    /bin/busybox sh
    
    • 1
    • 2
    • 3
    • 4
    • 5

    最后写成makefile生成即可

    initramfs:
            cd ./initramfs_dir && find . -print0 | cpio -ov --null --format=newc | gzip -9 > ../initramfs.img
    
    run:
            qemu-system-arm \
                    -M vexpress-a9 \
                    -dtb vexpress-v2p-ca9.dtb \
                    -kernel zImage \
                    -initrd initramfs.img \
                    -m 1G \
                    -nographic \
                    -append "earlyprintk=serial,ttyS0 console=ttyS0"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    第二个方法

    我们使用ramfs的方式来为内核提供根文件系统,内核默认的配置没有支持ramfs设备,我们需要添加对应的支持(CONFIG_BLK_DEV_RAM=y)

    make ARCH=arm menuconfig
    
    Device Drivers
        Block devices
            BLK_DEV_RAM
    
    • 1
    • 2
    • 3
    • 4
    • 5

    内核支持了ramfs设备之后,我们通过给qemu传递参数指定本机的相关文件作为ramfs的文件系统传递到内核,修改qemu启动命令

    qemu-system-aarch64 -machine virt       \
                        -cpu cortex-a53     \
                        -nographic          \
                        -smp 1              \
                        -m 2048             \
                        -kernel linux-4.19.171/arch/arm64/boot/Image                        \
                        -append "root=/dev/ram0 rootfstype=ramfs rw init=/init"             \
                        -initrd initramfs.cpio.gz
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    打包脚本mkinitramfs.sh内容:

    #!/bin/sh
    
    # Copyright 2006 Rob Landley  and TimeSys Corporation.
    # Licensed under GPL version 2
    
    if [ $# -ne 2 ]
    then
        echo "usage: mkinitramfs directory imagename.cpio.gz"
        exit 1
    fi
    
    if [ -d "$1" ]
    then
        echo "creating $2 from $1"
        (cd "$1"; find . | cpio -o -H newc | gzip) > "$2"
    else
        echo "First argument must be a directory"
        exit 1
    fi
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    ./mkinitramfs.sh  rootfs/ initramfs.cpio.gz
    
    • 1

    第三个方法

    创建rootfs根目录

    mkdir -p rootfs/{dev,etc/init.d,lib}
    
    • 1

    把busybox-1.20.2中的文件复制到rootfs根目录下,主要是一些基本的命令

    cp busybox-1.20.2/_install/* -r rootfs/
    
    • 1

    交叉编译工具链中的库文件复制到rootfs根目录的lib文件夹下

    sudo cp -P /usr/arm-linux-gnueabi/lib/* rootfs/lib/
    
    • 1

    制作根文件系统镜像 根文件系统镜像就相当于一个硬盘,就是把上面rootfs根目录中的所有文件复制到这个硬盘中。

    # 生成512M大小的磁盘镜像
    qemu-img create -f raw disk.img 512M
    # 把磁盘镜像格式化成ext4文件系统
    mkfs -t ext4 ./disk.img
    # 将rootfs根目录中的所有文件复制到磁盘镜像中 操作步骤是:创建挂载点-挂载-复制文件-卸载。
    mkdir tmpfs 
    sudo mount -o loop ./disk.img tmpfs/  
    sudo cp -r rootfs/* tmpfs/
    sudo umount tmpfs
    # 检查
    file disk.img
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    此时启动命令为

    # append表示传递给内核的参数 一般有根文件系统设备 文件系统类型 第一个进程名称
    qemu-system-arm -M vexpress-a9 -m 512M -kernel ./linux-4.14.212/arch/arm/boot/zImage -dtb  ./linux-4.14.212/arch/arm/boot/dts/vexpress-v2p-ca9.dtb -nographic -append "root=/dev/mmcblk0 rw console=ttyAMA0" -sd disk.img
    
    • 1
    • 2

    如果选择的是虚拟内存文件系统,请在配置内核的时候打开支持Gneral setup->initramfs/initrdDevice Drivers->Block devices->Ram block device support

    编译内核

    # ARCH:编译arch/目录下的哪一个子目录
    # CROSS_COMPILE:即交叉编译器的前缀
    make ARCH=arm CROSS_COMPILE=gcc-arm-linux-gnueabi-
    make dtbs 
    
    • 1
    • 2
    • 3
    • 4

    模拟系统

    qemu-system-arm 
    		-M vexpress-a9 
    		-m 256M -kernel arch/arm/boot/zImage 
    		-append "rdinit=/linuxrc console=ttyAMA0 loglevel=8" 
    		-dtb arch/arm/boot/dts/vexpress-v2p-ca9.dtb 
    		-nographic  
    
    # 以上命令中参数含义如下;
    # -M:指定硬件芯片框架
    # -m:指定运行内存大小
    # -kernel:指定运行的内核镜像
    # -dtb:指定具体芯片的配置信息
    # -nographic:指定不使用图形界面
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    运行结果

    # ...
    1000a000.uart: ttyAMA1 at MMIO 0x1000a000 (irq = 38, base_baud = 0) is a PL011 rev1
    1000b000.uart: ttyAMA2 at MMIO 0x1000b000 (irq = 39, base_baud = 0) is a PL011 rev1
    1000c000.uart: ttyAMA3 at MMIO 0x1000c000 (irq = 40, base_baud = 0) is a PL011 rev1
    rtc-pl031 10017000.rtc: registered as rtc0
    rtc-pl031 10017000.rtc: setting system clock to 2022-09-14T14:39:19 UTC (1663166359)
    amba 10020000.clcd: Fixing up cyclic dependency with 0-0039
    drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
    drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
    drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
    drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
    drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
    input: AT Raw Set 2 keyboard as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10006000.kmi/serio0/input/input0
    drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
    ALSA device list:
      #0: ARM AC'97 Interface PL041 rev0 at 0x10004000, irq 32
    drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
    Freeing unused kernel image (initmem) memory: 1024K
    drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
    Run /linuxrc as init process
    can't run '/etc/init.d/rcS': No such file or directory
    
    Please press Enter to activate this console. input: ImExPS/2 Generic Explorer Mouse as /devices/platform/bus@40000000/bus@40000000:motherboard-bus@40000000/bus@40000000:motherboard-bus@40000000:iofpga@7,00000000/10007000.kmi/serio1/input/input2
    drm-clcd-pl111 10020000.clcd: DVI muxed to daughterboard 1 (core tile) CLCD
    drm-clcd-pl111 10020000.clcd: initializing Versatile Express PL111
    ls
    / # ls
    bin      dev      linuxrc  root     sbin     usr
    / # pwd
    /
    / # mkdir mnt
    / # ls
    bin      dev      linuxrc  mnt      root     sbin     usr
    / # 
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    我觉得可以写一个makefile或者一个.sh来实现自动处理

    踩过的坑

    报错:can't open /dev/tty3: No such file or directory
    解决:

    sudo mknod tty1 c 4 1
    sudo mknod tty2 c 4 2
    sudo mknod tty3 c 4 3
    sudo mknod tty4 c 4 4
    
    • 1
    • 2
    • 3
    • 4

    报错:---[ end Kernel panic - not syncing: No working init found. Try passing init= option to kernel. See Linux Documentation/init.txt for guidance.
    解决:查看init文件格式与kernel文件格式匹配

    报错:---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
    解决:未安装文件系统

    其他方案

    ubuntu 交叉编译arm linux 内核小例子
    从源码编译安装 Linux 内核之二

    参考文章

  • 相关阅读:
    企业电子招投标采购系统源码之电子招投标的组成
    springBoot 项目中的静态资源文件夹static和模版文件文件夹templates
    7天酒店亮相“2022锦江行”17年国民历史酒店再启新程
    centos8如何安装nginx
    广西小贷牌照申请材料清单
    玩转云端 | 算力基础设施升级,看天翼云紫金DPU显身手!
    Postman —— 配置环境变量
    从技术全景到场景实战,透析「窄带高清」的演进突破
    day14--postman接口测试
    程序员脱单秘籍 | 我跟JVM搞对象!【深度剖析对象的创建和内存分配】
  • 原文地址:https://blog.csdn.net/qq_48322523/article/details/126842239