核心流程

首先,本文主要讲述如何编译Linux内核并在qemu虚拟机上运行。这里针对的架构是aarch64

本文的实验平台是Ubuntu 16.04

为了达成目标,我们需要有qemubuildrootlinux安装包或源码。

首先确保qemu-system-aarch64命令可用,可以通过在命令行执行qemu-system-aarch64 --version判断。

下载buildroot源码,链接见下文平台工具。假设其绝对路径保存在变量BUILD_ROOT_PATH中。执行以下命令

  1. cd $BUILD_ROOT_PATH
  2. make menuconfig

在弹出的配置界面中,设置Target option ---> Target ArchitectureAArch64 (little endian);设置Toolchain ---> Toolchain typeExternal toolchain,这时我们可以看到Toolchain ---> Toolchain的值为linaro AArch64 xxxx.xx;设置System configuration ---> Enable root login with password开启,并设置System configuration ---> Root passwordxxxx(任意的你喜欢的密码);设置System configuration ---> Run a getty (login prompt) after boot ---> TTY port的值为ttyAMA0(这一条非常重要,不然虚拟机可能启动不了);设置Target packages ---> Show packages that are also provided by busybox开启;设置Target packages ---> Debugging, profiling and benchmark ---> strace开启;设置Filesystem images ---> cpio the root filesystem开启。

在配置完成之后,执行

  1. make

注意:这里可能需要配置wget代理。

生成的rootfs.cpio在目录$BUILD_ROOT_PATH/output/images下面。

下载Linux内核源码,链接见下文平台工具。假设其绝对路径保存在变量LINUX_KERNEL_PATH中。执行以下命令

  1. cd $LINUX_KERNEL_PATH
  2. ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
  3. vim .config

在打开的文件中,找到CONFIG_CMDLINE这个配置选项,设置其值为console=ttyAMA0;找到CONFIG_INITRAMFS_SOURCE这个配置选项,设置其值为$BUILD_ROOT_PATH/output/images/rootfs.cpio(注意,这里要自己展开变量BUILD_ROOT_PATH);设置CONFIG_DEBUG_INFO配置项为y

配置结束后,执行以下命令

  1. ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j16

执行结束后,我们可以看到生成了一些文件,其中包括$LINUX_KERNEL_PATH/vmlinux$LINUX_KERNEL_PATH/arch/arm64/boot/Image

在当前目录创建一个shell脚本,避免重复输入指令。其文件名为start.sh,其内容为

  1. qemu-system-aarch64 -machine virt -cpu cortex-a57 \
  2. -machine type=virt -nographic -smp 1 \
  3. -m 2048 \
  4. -kernel ./arch/arm64/boot/Image \
  5. --apend "console=ttyAMA0" \
  6. $1 $2

执行./startup.sh,这是可以用qemu启动linux内核。在进入命令行之前,需要输入buildroot login: 的值,其值为root,然后需要输入Password: ,这是前文构建rootfs.cpio的时候,配置项System configuration ---> Root password的值。然后就可以进入命令行执行以下常用命令了。(注意,需要先cd /

如果要退出qemu,可以先按Ctrl + A,然后按X

为了在主机和qemu虚拟机之间共享文件,我们可以创建一个目录,其绝对路径为SHARED_FILE_PATH。然后执行以下命令

  1. cd $BUILD_ROOT_PATH
  2. vim .config

修改BR2_ROOTFS_OVERLAY配置项的值为$SHARED_FILE_PATH(注意,自行展开变量)。

保存后执行以下命令重新创建 rootfs.cpio

  1. rm $BUILD_ROOT_PATH/output/images/rootfs.*
  2. make

然后需要重新编译内核,即

  1. cd $LINUX_KERNEL_PATH
  2. ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j16

依然通过./start.sh启动虚拟机跑linux内核,进入命令行后,执行cd /; ls,我们可以看到$SHARED_FILE_PATH目录下的文件。

重新执行./start.sh -s -S进入qemu的调试状态,然后开一个新的shell,输入命令

  1. cd $LINUX_KERNEL_PATH
  2. aarch64-linux-gnu-gdb ./vmlinux -ex "target remote :1234"

现在,可以像以往一样使用gdb进行调试了……

下面介绍如何编译一个linux内核模块。

  1. cd $SHARED_FILE_PATH
  2. vim hello.c

hello.c的内容为

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>
  4. #include <linux/seq_file.h>
  5. #include <linux/proc_fs.h>
  6. #include <linux/sched.h>
  7. int helloinit(void)
  8. {
  9. printk(KERN_DEBUG "hello world !!\n");
  10. return 0;
  11. }
  12. void helloexit(void)
  13. {
  14. printk(KERN_DEBUG "goodbye world !!\n");
  15. }
  16. module_init(helloinit);
  17. module_exit(helloexit);
  18. MODULE_LICENSE("GPL");

然后在当前目录创建Makefile内容如下

  1. ifneq (${KERNELRELEASE},)
  2. obj-m := hello.o
  3. else
  4. KERNEL_SOURCE := $LINUX_KERNEL_PATH # 注意自行展开变量LINUX_KERNEL_PATH
  5. PWD := $(shell pwd)
  6. default:
  7. ${MAKE} -C ${KERNEL_SOURCE} M=${PWD} modules
  8. clean:
  9. ${MAKE} -C ${KERNEL_SOURCE} M=${PWD} clean
  10. endif

然后执行交叉编译命令

  1. ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make

OK,重新编译rootfs.cpiolinux内核,然后运行qemu。在进入linux命令行后,执行以下命令

  1. cd /
  2. insmod hello.ko
  3. dmesg | tail # 可以看到打印信息 hello world !!
  4. rmmod hello.ko
  5. dmesg | tail # 可以看到打印信息 goodbye world !!

相关经验

Linux Kernel

  • 使用qemu并开启gdb server功能之后,在gdb窗口输入b start_kernel,进入最初的内核初始化函数。

平台工具

参考

编译aarch64 Linux内核并基于qemu运行的更多相关文章

  1. 编译x86_64 Linux内核并基于QEMU运行

    编译并运行内核镜像 安装包准备 $ sudo apt install git $ sudo apt install build-essential kernel-package fakeroot li ...

  2. 编译安装linux内核步骤

    编译安装linux内核步骤: 一.获取内核源码 源码网址:www.kernel.org 二.解压内核源码 首先以root帐号登录,然后进入/usr/src子目录.如果用户在安装Linux时,安装了内核 ...

  3. 【转】6.4.6 将驱动编译进Linux内核进行测试

    原文网址:http://www.apkbus.com/android-98520-1-1.html 前面几节都是将Linux驱动编译成模块,然后动态装载进行测试.动态装载驱动模块不会随着Android ...

  4. linux内核系列(一)编译安装Linux内核 2.6.18

    1.配置环境 操作系统:CentOS 5.2 下载linux-2.6.18版本的内核,网址:http://www.kernel.org 说明:该编译文档适合2.6.18以上的Linux内核版本,只需所 ...

  5. 将MPLS编译进linux内核中

    系统环境:linux kernel 2.6.35.(此环境是上一篇文章中将ubuntu内核替换后的环境) 编译过程如下: 1)首先需要下载patch文件:linux-kernel-v2.6.35-mp ...

  6. 将驱动编译进Linux内核

    *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...

  7. 如何编译安装Linux内核

    操作系统环境 VMware workstation15 Pro ubuntu18.04 LTS 待编译内核5.3.10版本 内核下载地址 kernel.org 环境配置 在正式编译前需要安装部分软件. ...

  8. 编译最新linux内核(version 4.4.2)

    环境:centos6.4 内核版本为2.6.32 目标:编译4.4.2内核,升级到 4.4.2 准备工作: 安装开发库和ncurses库 # yum groupinstall "Develo ...

  9. armv8(aarch64)linux内核中flush_dcache_all函数详细分析【转】

    转自:http://blog.csdn.net/qianlong4526888/article/details/12062809 版权声明:本文为博主原创文章,未经博主允许不得转载. /* *  __ ...

随机推荐

  1. 联想INTEL X86台式机 用光驱启动 usb光驱启动

    联想INTEL X86台式机  用光驱启动 usb光驱启动 启动项顺序 都要调整 主要顺序 自动顺序 出错顺序 按下f10 f12

  2. Windows 10 创建虚拟网卡

    想把虚拟机桥接到我的电脑,但我连的是无线网电脑没查网线,所以就创建个虚拟网卡吧. 1.win + x 打开设备管理器 2.网络适配器  + 操作 + 添加过时硬件  3.下一步  4.选-->安 ...

  3. KVM虚拟化存储管理(4)

    一.KVM存储虚拟化介绍 KVM 的存储虚拟化是通过存储池(Storage Pool)和卷(Volume)来管理的. Storage Pool 是宿主机上可以看到的一片存储空间,可以是多种型: Vol ...

  4. nosql数据库之Redis集群

    Redis 集群是一个可以在多个 Redis 节点之间进行数据共享的设施(installation). Redis 集群不支持那些需要同时处理多个键的 Redis 命令, 因为执行这些命令需要在多个 ...

  5. Redis(3)- 数据结构

    一.Redis数据结构 Redis数据结构:Redis在数据类型上常用的有5种数据类型,而底层实现拥有种.可以使用命令OBJECT ENCODING K1查询底层数据结构. # 查询key的底层数据类 ...

  6. SpringBoot打jar包-下载文件时报错-class path resource xxxxxx cannot be resolved to URL because it does not exist

    一.问题由来 新项目的开发中,打包方式由war包改为了jar包的方式,这样在部署的时候更加的方便.测试环境使用pm2这个工具来管理项目的运行,停止,重启等等非常方便. 可是当测试人员在测试项目中的文件 ...

  7. UEFI和Legacy兼容启动U盘制作

    应用场景 自己有一个可启动移动硬盘,是属于老式的BIOS启动方式,最近换了新电脑,因为电脑只支持uefi的启动方式,所以决心为移动硬盘增加uefi启动支持,如何将一个只支持BIOS启动(或者 Lega ...

  8. SQLZOO

    一.SELECT basics/zh 以顯示德國 Germany 的人口. select population from world where name = 'Germany'; 查詢面積為 5,0 ...

  9. XShell本地上传文件到Ubuntu上及从Ubuntu下载文件到本地

    使用XShell本地上传文件到Ubuntu上及从Ubuntu下载文件到本地. 1.第一种方法是最常用的 :如果下载了Xshell和Xftp,Ctrl+Alt+F就可以选择文件的互传了!(虚拟机/云服务 ...

  10. 【进阶之路】多线程条件下分段处理List集合的几种方法

    这两个月来因为工作和家庭的事情,导致一直都很忙,没有多少时间去汲取养分,也就没有什么产出,最近稍微轻松了一点,后续的[进阶之路]会慢慢回到正轨. 开门见山的说,第一次接触到多线程处理同一个任务,是使用 ...