核心流程

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

本文的实验平台是Ubuntu 16.04

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

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

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

cd $BUILD_ROOT_PATH
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开启。

在配置完成之后,执行

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.cpiolinux内核,然后运行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,进入最初的内核初始化函数。

平台工具

参考

编译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. Linux用户登录查看命令总结 - w,who,last,lastlog

    Linux用户登录查看命令总结 - w,who,last,lastlog linux shell 747 次阅读  ·  读完需要 15 分钟 0 1. 查看登录用户信息 who -H 命令输出 NA ...

  2. 一、apt的简介

    一.apt的简介 apt的全称是Advanced Packaging Tool是Linux系统下的一款安装包管理工具. 最初需要在Linux系统中安装软件,需要自行编译各类软件,缺乏一个统一管理软件包 ...

  3. 分布式存储ceph---ceph概念及原理(1)

    一.Ceph简介: Ceph是一种为优秀的性能.可靠性和可扩展性而设计的统一的.分布式文件系统.ceph 的统一体现在可以提供文件系统.块存储和对象存储,分布式体现在可以动态扩展.在国内一些公司的云环 ...

  4. WIFF SD卡

    https://detail.tmall.com/item.htm?spm=a230r.1.14.1.2d4d6923Fq3Hgx&id=36945441834&cm_id=14010 ...

  5. 科普 AF摄像头

    AF(Auto Focus)自动对焦:自动对焦有两种方式,根据控制原理分为主动式和被动式两种.主动式自动对焦通过相机发射红外线,根据反射回来的射线信号确定被摄体的距离,再自动调节镜头,实现自动对焦.被 ...

  6. 【odoo14】【用户侧】权限配置

    以下内容仅适用于odoo的客户,不适用于开发人员. 下文介绍中涉及的概念及UI均是在odoo14社区版中进行. 目录 一. odoo中的对象 二. 权限控制 2.1 实现原理 2.2 UI方式实现权限 ...

  7. docker私有仓库搭建及使用

      1.下载官方镜像 sudo docker pull registry 下载完成后,docker images可以查看到pull下来的镜像registry 2.启动registry容器,用于提供私有 ...

  8. Step By Step(Lua函数)

    Step By Step(Lua函数) 一.函数:    在Lua中函数的调用方式和C语言基本相同,如:print("Hello World")和a = add(x, y).唯一的 ...

  9. Python+Selenium学习笔记11 - python官网的tutorial - 定义函数

    1 def f(a, L=[]): 2 L.append(a) 3 return L 4 5 print f(5) 6 print f(2) 输出 1 def f(a, L=None): 2 if L ...

  10. windows使用attrib来简单隐藏文件

    效果如下: 详细命令说明: ATTRIB [+R | -R] [+A | -A] [+S | -S] [+H | -H] [+O | -O] [+I | -I] [+X | -X] [+P | -P] ...