3829|1

64

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

一起读《奔跑吧Linux内核(第2版)卷2:调试与案例分析》- 内核调试 [复制链接]

 

这一章一起动手做一下内核的调试。

 

环境这块折腾了很久,之前都是Ubuntu14的,现在这个需要更新到Ubuntu22才可以~,大家动手做实验的时候注意啦!

 

一、搭建QEMU+Debian实验平台

 

一、安装工具

1.1、Linux主机安装需要的工具包

 

sudo apt-get install qemu libncurses5-dev gcc-aarch64-linux-gnu build-essential git bison flex libssl-dev qemu-system-arm

 

1.2、安装完成后,检查QEMU版本

 

qemu-system-aarch64 --version

 

 

 

二、下载源码

下载runninglinuxkernel_5.0源码

 

git clone https://gitee.com/zhang-ge/runninglinuxkernel_5.0.git

 

 

 

二、运行实验平台

 

一、编译内核

 

cd runninglinuxkernel_5.0

 

如果在编译内核之前想进入menuconfig界面来配置内核:

 

git checkout rlk_5.0

 

./run_debian_arm64.sh menuconfig

 

编译内核。

 

$ ./run_debian_arm64.sh build_kernel

 

执行上述脚本需要几十分钟,依赖于主机的计算能力。接着,编译根文件系统。

 

$ sudo ./run_debian_arm64.sh build_rootfs

 

编译根文件系统需要管理员权限,而编译内核则不需要。

执行完成后会生成一个名为rootfs_arm64.ext4的根文件系统。

 

 

 

二、运行系统

运行刚才编译好的ARM64版本的Linux系统。

运行run_debian_arm64.sh脚本,输入run参数即可。

 

$./run_debian_arm64.sh run

系统登录名: benshushu 密码:123

切换到root用户:su root

 

 

 

三、实验平台初体验

一、在线安装软件包

QEMU虚拟机可以通过VirtIO-Net技术来生成一个虚拟的网卡,通过NAT网络桥接技术和主机进行网络共享。使用ifconfig命令来检查网络配置。

 

但这里我发现ifconfig不起作用,系统返回 bash: ifconfig: command not found 错误说明系统无法找到 ifconfig 命令。这可能是因为最新版本的Linux发行版中已经不推荐使用ifconfig命令了,而应该使用ip命令来替代。

 

可以尝试使用以下命令来代替ifconfig:

 

ip addr show

 

 

 

可以看到生成了一个名为enp0s1的网卡设备,分配的IP地址为:10.0.2.15。

 

提前更改系统时间

 

root@ubuntu:~# date -s 2020-03-29 #假设最新日期是2020年3月29日Sun Mar 29 00:00:00 UTC 2020

 

这里需要提前导入新的 GPG 密钥,使用以下命令:

 

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 0E98404D386FA1D9

 

通过apt update命令来更新Debian系统的软件仓库。

 

apt update

 

 

 

使用apt install命令来安装软件包。比如,可以在线安装gcc。

 

root@ubuntu:~# apt install gcc

 

二、共享文件夹

在主机和QEMU虚拟机之间共享文件。 主机和QEMU虚拟机可以通过NET_9P技术进行文件共享,这个需要QEMU虚拟机和主机的Linux内核都使能NET_9P的内核模块。

 

本实验平台已经支持主机和QEMU虚拟机的共享文件,可以通过如下简单方法来测试。

 

复制一个文件到runninglinuxkernel_5.0/kmodules目录下面。

 

$ cp test.c runninglinuxkernel_5.0/kmodules

 

启动QEMU虚拟机之后,首先检查一下/mnt目录是否有test.c文件。

 

root@ubuntu:/# cd /mnt root@ubuntu:/mnt # ls README test.c

 

我们在后续的实验中会经常利用这个特性,比如把编译好的内核模块或者内核模块源代码放入QEMU虚拟机。

 

四、编译加载模块及单步调试内核

 

一、编译加载内核模块

 

在本书中,常常需要编译内核模块并放入QEMU虚拟机中以加载内核模块。我们这里提供两种编译内核模块的方法。一种是在主机上交叉编译,然后共享到QEMU虚拟机,另一种方法是在QEMU虚拟机里本地编译。

 

首先,在QEMU虚拟机中安装必要的软件包。

 

root@ubuntu: # apt install build-essential

 

在QEMU虚拟机里编译内核模块时需要指定QEMU虚拟机本地的内核路径,例如BASEINCLUDE变量指向了本地内核路径。

 

“/lib/modules/$(shell uname -r)/build”是一个链接文件,用来指向具体内核源代码路径,通常是指向已经编译过的内核路径。

 

BASEINCLUDE ?= /lib/modules/$(shell uname -r)/build

 

编译内核模块,下面以最简单的hello_world内核模块程序为例。

 

cd hello_world #进入内核模块代码所在的目录
export ARCH=arm64
export CROSS_COMPILE=aarch64-linux-gnu-
root@ubuntu:/mnt/hello_world# make
make -C /lib/modules/5.0.0+/build M=/mnt/hello_world modules;
make[1]: Entering directory '/usr/src/linux'  
CC [M]  /mnt/hello_world/test-1.o  
LD [M]  /mnt/hello_world/test.o  
Building modules, stage 2.  
MODPOST 1 modules  
CC      /mnt/hello_world/test.mod.o  
LD [M]  /mnt/hello_world /test.ko
make[1]: Leaving directory '/usr/src/linux'
root@ubuntu: /mnt/hello_world#

 

提前编写modules_helloworld.c、Makefile文件

#include <linux/init.h>  
#include <linux/module.h>

int hello_init(void)
{
    printk("enter hello world!\n");
    return 0;
}
void hello_exit(void)
{
    printk("exit hello world!\n");
}


module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");

 

BASEINCLUDE ?= /lib/modules/$(shell uname -r)/build
CURRENT_PATH := $(shell pwd)
obj-m := modules_helloworld.o

build: kernel_modules

kernel_modules:
                $(MAKE) -C $(BASEINCLUDE) M=$(CURRENT_PATH) modules
clean:
                $(MAKE) -C $(BASEINCLUDE) M=$(CURRENT_PATH) clean

 

编译

 

 

 

运行,这里可能insmod不成功,而insmod和modprobe命令的可执行文件都可以在/sbin目录中找到,这意味着这两个命令应该已经正确安装在系统中了。

 

根据您之前尝试过的加载模块的命令和报错信息,看起来问题可能是命令使用方式不正确。

 

使用以下命令加载模块:

 

/sbin/insmod modules_helloworld.ko

 

 

 

二、单步调试ARM64 Linux内核

Ubuntu提前安装gdb-multiarch

 

sudo apt install gdb-multiarch

 

再进入实验平台时,加上启动GDB

 

./run_debian_arm64.sh run debug

 

上述脚本会运行如下命令。

 

-S:表示QEMU虚拟机会冻结CPU,直到在远程的GDB中输入相应控制命令。

-s:表示在1234端口接受GDB的调试连接。

 

接下来,在另外一个超级终端中启动GDB。

 

linux@linux-virtual-machine:~$ cd Desktop/work/runninglinuxkernel_5.0/
linux@linux-virtual-machine:~/Desktop/work/runninglinuxkernel_5.0$ gdb-multiarch --tui vmlinux

 

此时会来到GDB端口:

 

 

(gdb) set architecture aarch64   //设置aarch64架构
(gdb) target remote localhost:1234 //通过1234端口远程连接到QEMU虚拟机
(gdb) b start_kernel //在内核的start_kernel处设置断点
(gdb) c

 

如图所示,GDB开始接管Linux内核运行,并且到断点处暂停,这时即可使用GDB命令来调试内核。

 

五、总结

 

总之,这部分实验还是比较轻松的,实现了QEMU+Debian实验平台 的搭建和编译加载模块及单步调试内核。

以后可以基于此来调试Linux,当系统发生段错误或崩溃,都可以使用GDB来排查错误了,是工作中非常实用的技巧!

 

最新回复

nmg
第一次见到网友说Ubuntu14,你这版本竟然可以低到这个程度   详情 回复 发表于 2024-4-22 10:05
点赞 关注

回复
举报

5263

帖子

236

TA的资源

管理员

沙发
 

第一次见到网友说Ubuntu14,你这版本竟然可以低到这个程度

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
 
 

回复
您需要登录后才可以回帖 登录 | 注册

随便看看
查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/6 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表