编译aarch64 Linux内核并基于qemu运行
核心流程
首先,本文主要讲述如何编译Linux内核并在qemu虚拟机上运行。这里针对的架构是aarch64。
本文的实验平台是Ubuntu 16.04。
为了达成目标,我们需要有qemu、buildroot和linux安装包或源码。
首先确保qemu-system-aarch64命令可用,可以通过在命令行执行qemu-system-aarch64 --version判断。
下载buildroot源码,链接见下文平台工具。假设其绝对路径保存在变量BUILD_ROOT_PATH中。执行以下命令
cd $BUILD_ROOT_PATH
make menuconfig
在弹出的配置界面中,设置Target option ---> Target Architecture为AArch64 (little endian);设置Toolchain ---> Toolchain type为External toolchain,这时我们可以看到Toolchain ---> Toolchain的值为linaro AArch64 xxxx.xx;设置System configuration ---> Enable root login with password开启,并设置System configuration ---> Root password为xxxx(任意的你喜欢的密码);设置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开启。
在配置完成之后,执行
make
注意:这里可能需要配置wget代理。
生成的rootfs.cpio在目录$BUILD_ROOT_PATH/output/images下面。
下载Linux内核源码,链接见下文平台工具。假设其绝对路径保存在变量LINUX_KERNEL_PATH中。执行以下命令
cd $LINUX_KERNEL_PATH
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make defconfig
vim .config
在打开的文件中,找到CONFIG_CMDLINE这个配置选项,设置其值为console=ttyAMA0;找到CONFIG_INITRAMFS_SOURCE这个配置选项,设置其值为$BUILD_ROOT_PATH/output/images/rootfs.cpio(注意,这里要自己展开变量BUILD_ROOT_PATH);设置CONFIG_DEBUG_INFO配置项为y。
配置结束后,执行以下命令
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j16
执行结束后,我们可以看到生成了一些文件,其中包括$LINUX_KERNEL_PATH/vmlinux和$LINUX_KERNEL_PATH/arch/arm64/boot/Image
在当前目录创建一个shell脚本,避免重复输入指令。其文件名为start.sh,其内容为
qemu-system-aarch64 -machine virt -cpu cortex-a57 \
-machine type=virt -nographic -smp 1 \
-m 2048 \
-kernel ./arch/arm64/boot/Image \
--apend "console=ttyAMA0" \
$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。然后执行以下命令
cd $BUILD_ROOT_PATH
vim .config
修改BR2_ROOTFS_OVERLAY配置项的值为$SHARED_FILE_PATH(注意,自行展开变量)。
保存后执行以下命令重新创建 rootfs.cpio。
rm $BUILD_ROOT_PATH/output/images/rootfs.*
make
然后需要重新编译内核,即
cd $LINUX_KERNEL_PATH
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make -j16
依然通过./start.sh启动虚拟机跑linux内核,进入命令行后,执行cd /; ls,我们可以看到$SHARED_FILE_PATH目录下的文件。
重新执行./start.sh -s -S进入qemu的调试状态,然后开一个新的shell,输入命令
cd $LINUX_KERNEL_PATH
aarch64-linux-gnu-gdb ./vmlinux -ex "target remote :1234"
现在,可以像以往一样使用gdb进行调试了……
下面介绍如何编译一个linux内核模块。
cd $SHARED_FILE_PATH
vim hello.c
hello.c的内容为
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/proc_fs.h>
#include <linux/sched.h>
int helloinit(void)
{
printk(KERN_DEBUG "hello world !!\n");
return 0;
}
void helloexit(void)
{
printk(KERN_DEBUG "goodbye world !!\n");
}
module_init(helloinit);
module_exit(helloexit);
MODULE_LICENSE("GPL");
然后在当前目录创建Makefile内容如下
ifneq (${KERNELRELEASE},)
obj-m := hello.o
else
KERNEL_SOURCE := $LINUX_KERNEL_PATH # 注意自行展开变量LINUX_KERNEL_PATH
PWD := $(shell pwd)
default:
${MAKE} -C ${KERNEL_SOURCE} M=${PWD} modules
clean:
${MAKE} -C ${KERNEL_SOURCE} M=${PWD} clean
endif
然后执行交叉编译命令
ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- make
OK,重新编译rootfs.cpio和linux内核,然后运行qemu。在进入linux命令行后,执行以下命令
cd /
insmod hello.ko
dmesg | tail # 可以看到打印信息 hello world !!
rmmod hello.ko
dmesg | tail # 可以看到打印信息 goodbye world !!
相关经验
Linux Kernel
- 使用
qemu并开启gdb server功能之后,在gdb窗口输入b start_kernel,进入最初的内核初始化函数。
平台工具
参考
- Starting Linux kernel exploration
- Debugging an ARM64 linux kernel using QEMU
- Writing kernel modules
- Debugging Kernel and Modules using GDB
编译aarch64 Linux内核并基于qemu运行的更多相关文章
- 编译x86_64 Linux内核并基于QEMU运行
编译并运行内核镜像 安装包准备 $ sudo apt install git $ sudo apt install build-essential kernel-package fakeroot li ...
- 编译安装linux内核步骤
编译安装linux内核步骤: 一.获取内核源码 源码网址:www.kernel.org 二.解压内核源码 首先以root帐号登录,然后进入/usr/src子目录.如果用户在安装Linux时,安装了内核 ...
- 【转】6.4.6 将驱动编译进Linux内核进行测试
原文网址:http://www.apkbus.com/android-98520-1-1.html 前面几节都是将Linux驱动编译成模块,然后动态装载进行测试.动态装载驱动模块不会随着Android ...
- linux内核系列(一)编译安装Linux内核 2.6.18
1.配置环境 操作系统:CentOS 5.2 下载linux-2.6.18版本的内核,网址:http://www.kernel.org 说明:该编译文档适合2.6.18以上的Linux内核版本,只需所 ...
- 将MPLS编译进linux内核中
系统环境:linux kernel 2.6.35.(此环境是上一篇文章中将ubuntu内核替换后的环境) 编译过程如下: 1)首先需要下载patch文件:linux-kernel-v2.6.35-mp ...
- 将驱动编译进Linux内核
*:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: 0 !important; } /* ...
- 如何编译安装Linux内核
操作系统环境 VMware workstation15 Pro ubuntu18.04 LTS 待编译内核5.3.10版本 内核下载地址 kernel.org 环境配置 在正式编译前需要安装部分软件. ...
- 编译最新linux内核(version 4.4.2)
环境:centos6.4 内核版本为2.6.32 目标:编译4.4.2内核,升级到 4.4.2 准备工作: 安装开发库和ncurses库 # yum groupinstall "Develo ...
- armv8(aarch64)linux内核中flush_dcache_all函数详细分析【转】
转自:http://blog.csdn.net/qianlong4526888/article/details/12062809 版权声明:本文为博主原创文章,未经博主允许不得转载. /* * __ ...
随机推荐
- [Linux-网络性能测试] -- netperf测试
[Linux-网络性能测试] -- netperf测试 2017.01.17 14:15:54字数 1599阅读 4400 简述 Netperf是一种网络性能的测量工具(由惠普公司开发的,测试网络栈. ...
- 把一个整体目标设置成多个分阶段目标,完成了一个目标后,就相当于一件事OVER
如果事情有变坏的可能,不管这种可能性有多小,它总会发生 . 一.任何事都没有表面看起来那么简单:二.所有的事都会比你预计的时间长:三.会出错的事总会出错:四.如果你担心某种情况发生,那么它就一定会发生 ...
- Linux_yum仓库管理
一.yum配置本地仓库 1.挂载光盘 [root@localhost ~]# mount /dev/sr0 /mnt/ [root@localhost ~]# df -hT 文件系统 类型 容量 已用 ...
- HDFS 高可用(HA)环境搭建
步骤一:修改公共属性配置 core-site.xml 文件 [root@node-01 ~]# cd /root/apps/hadoop-3.2.1/etc/hadoop [root@node-01 ...
- GCC编译 C与C++ C89与C99
1) 最初的 ANSI C 标准 (X3.159-1989) 在 1989 年被批准,并于 1990 年发布.稍后这个标准被接受为 ISO 标准 (ISO/IEC 9899:1990) .虽然 ISO ...
- Azure Synapse Link for Dataverse
MyBuild - Scale, analyze and serve Microsoft Dynamics 365 application data with Azure 本周的微软Bulid大会上发 ...
- Spring的三种注入
在学习Spring的过程中,其中一个很重要的就是依赖注入DI,在此总结一下 注入方式有三种: 一.构造器注入 二.Set方式注入(重点) 三.扩展方式注入 构造器注入: a.默认使用无参构造函数创建对 ...
- CVPR目标检测与实例分割算法解析:FCOS(2019),Mask R-CNN(2019),PolarMask(2020)
CVPR目标检测与实例分割算法解析:FCOS(2019),Mask R-CNN(2019),PolarMask(2020)1. 目标检测:FCOS(CVPR 2019)目标检测算法FCOS(FCOS: ...
- Nsight Compute Profilier 分析
profiler报告包含每次内核启动分析期间收集的所有信息.在用户界面中,它包含一个包含常规信息的标题,以及用于在报告页面或单个收集的启动之间切换的控件.默认情况下,报告以选定的详细信息页面开始. 页 ...
- Redis系列(五):消息队列
消息队列已经成为现在互联网服务端的标配组件,现在比较常用的消息中间件有RabbitMQ.Kafka.RocketMQ.ActiveMQ.说出来你可能不信,Redis作为一个缓存中间件,居然也提供了消息 ...