qemu+emacs+gdb调试内核

本文详细介绍了如何使用Emacs和GDB进行内核远程调试的过程,包括环境配置、编译内核、设置参数以启用gdb模式、修改源代码以适应调试需求、使用qemu进行启动和调试等步骤。通过提供具体实例,帮助开发者掌握内核调试技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

emacs -nw


[b]1.debug方式编译内核
2.qemu -S启动
3.设置emacs参数 ,启用gdb模式远程调试[/b]

[b]环境:[/b]
[code="java"]
# cat /etc/redhat-release
CentOS Linux release 7.1.1503 (Core)
# gcc --version
gcc (GCC) 4.8.3 20140911 (Red Hat 4.8.3-9)
Copyright (C) 2013 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
[/code]
下载linux-2.6.20
[url]http://www.linux-mips.org/pub/linux/mips/kernel/v2.6/[/url]
修改Makefile

1438 # Modules
1439 %/: prepare scripts FORCE
1440 $(Q)$(MAKE) KBUILD_MODULES=$(if $(CONFIG_MODULES),1) \
1441 $(build)=$(build-dir)


412 %config: scripts_basic outputmakefile FORCE
413 $(Q)mkdir -p include/linux include/config
414 $(Q)$(MAKE) $(build)=scripts/kconfig $@

make defconfig
生成.config文件
[b][color=red]
这里如果使用这种方式生成的.config文件内核可以编译成功,但是在可能无法进入linux操作系统,尝试使用fabrice bellard的jslinux的配置文件
linuxstart-20120111/config_linux-2.6.20
[/color][/b]
[url]http://bellard.org/jslinux/tech.html[/url]
下载配置文件
[url]http://dl.iteye.com/topics/download/9973ef69-2386-36bb-82f5-1c01a6edabac[/url]
把这个保存成.config放到和Makefile同级的目录下
make menuconfig
选择debug模式
[img]http://dl2.iteye.com/upload/attachment/0113/4982/dbfb744d-24b2-3380-afc1-d1d4f0df1135.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0113/4978/1e2e82c7-1ee7-3e18-8d14-a8c9ba0aedd9.png[/img]
[img]http://dl2.iteye.com/upload/attachment/0113/4980/0255469f-1c26-31b4-a890-24ad67c6e5a4.png[/img]

vim scripts/mod/sumversion.c
最上面新加一行

#include <limits.h>

[color=red] vim arch/i386/kernel/Makefile[/color]
gcc的版本问题
gcc的参数-m elf_i386改成-m32
ld后的参数不改

57 # The DSO images are built using a special linker script.
58 quiet_cmd_syscall = SYSCALL $@
59 cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \
60 -Wl,-T,$(filter-out FORCE,$^) -o $@
61

改成

57 # The DSO images are built using a special linker script.
58 quiet_cmd_syscall = SYSCALL $@
59 cmd_syscall = $(CC) -m32 -nostdlib $(SYSCFLAGS_$(@F)) \
60 -Wl,-T,$(filter-out FORCE,$^) -o $@
61

vim kernel/mutex.c

__mutex_lock_slowpath 的两个方法的static去掉
__mutex_unlock_slowpath的两个方法的static去掉


开始make

make ARCH=i386 -j16

用qemu启动内核

/usr/libexec/qemu-kvm -kernel linux-2.6.20.jslinux/arch/i386/boot/bzImage -hda hda.bin -append "root=/dev/hda console=ttyS0" -serial stdio -vnc 0.0.0.0:3

或者使用qemu的官网的test的img:linux-0.2.img

/usr/libexec/qemu-kvm -kernel linux-2.6.20.jslinux/arch/i386/boot/bzImage -hda linux-0.2.img -append "root=/dev/hda console=ttyS0" -serial stdio -vnc 0.0.0.0:3

注意:这里加了console=ttyS0 才有很多输出信息,不加没有
注意:这里的hda.bin是fabrice bellard的jslinux中的
注意,这里加了 -serial 才输出到屏幕上,在vnc连进去还是到"ok,booting the kernel"
如果不开-s和-S的调试模式,直接气得弄个qemu的话,append参数里面有console则会在当前命令行进入系统
[img]http://dl2.iteye.com/upload/attachment/0113/5725/7556e63c-8335-3382-afcd-16ba870df730.png[/img]


可以使用qemu官方的linux-0.2.img(不过这个img自带2.6.20的内核,不影响)
如果不适用我们编译的内核,而直接用他自己的内核

/usr/libexec/qemu-kvm linux-0.2.img -vnc 0.0.0.0:3

vnc连接后
可以去看一下内核的版本
[img]http://dl2.iteye.com/upload/attachment/0113/5727/8e45f25a-746a-3ce3-be5a-8f33ff9957cb.png[/img]

其中-S 是gdb需要的
远程使用vnc 端口3或者5903
[img]http://dl2.iteye.com/upload/attachment/0113/4984/3348711e-96fd-3ade-b334-457548d2b054.png[/img]
进入后应该是一片漆黑

ctl+alt+2
进入qemu调试
然后输入gdbserver回车
默认开启1234端口
指定端口用
(qemu) gdbserver tcp::1233
如果省去gdbserver这步骤
可以启动的时候直接加-s 注意小s是启动server,大S是暂停

/usr/libexec/qemu-kvm -kernel linux-2.6.20.debug/arch/i386/boot/bzImage -hda hda.bin -append "root=/dev/hda" -serial stdio -vnc 0.0.0.0:3 -S -s

[img]http://dl2.iteye.com/upload/attachment/0113/4986/a650d497-d197-3f64-b54b-f2c8be1e5d59.png[/img]
可以netstat一下1234端口是否打开

netstat -nltp |grep 1234


进入linux-2.6.20目录
下面有个vmlinux

[b]如果不使用emacs[/b]
直接gdb vmlinux
进入后
target remote localhost:1234

[b]如果使用emacs:[/b]
emacs
M-x gdb
Run gdb (like this): gdb -i=mi vmlinux
这里需要设置一下,否则会出现
get Non-stop mode requested, but remote does not support non-stop

的错误
设置方法如下
[url]http://stackoverflow.com/questions/15274798/valgrind-vgdb-with-gdb-in-emacs[/url]

M-x customize-option
[img]http://dl2.iteye.com/upload/attachment/0113/4988/1b8fb5cb-a000-365a-9c57-9607dfef985c.png[/img]

[color=red]Customize variable: gdb-non-stop-setting[/color]
[img]http://dl2.iteye.com/upload/attachment/0113/4990/8b69158f-66a7-3ba2-8bd8-57573dc6c806.png[/img]
在state上回车
修改成
[img]http://dl2.iteye.com/upload/attachment/0113/4992/fe2a70a2-6935-38ba-8ba4-5248d9a2e342.png[/img]
可以看到在~/.emacs里面多了

(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(gdb-non-stop-setting nil))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
~

回到
M-x gdb
target remote localhost:1234
M-x gdb-many-windows
[img]http://dl2.iteye.com/upload/attachment/0113/4994/924a53d1-2d54-3f56-aec7-74bc453bd4ca.png[/img]
在gdb下 info source 查看当前文件的名字
[b]开始enjoy吧[/b]


另外,linux追代码的时候如果使用vim
编译完内核后到linux-2.6.20目录
make tags
生成ctags文件
这样比自己生成的ctags要准,自己生成的当函数重名的时候会跳错乱
配置~/.vimrc

syntax on
set tabstop=4
set paste
set tags=/home/haoning/rtclinux/websocket/web/jslinux/tmp/linux-2.6.20.jslinux/tags



备注:如果有linux启动不了的问题参考
[url]http://processors.wiki.ti.com/index.php/Kernel_-_Common_Problems_Booting_Linux[/url]
[url]http://serverfault.com/questions/471719/how-to-start-qemu-directly-in-the-console-not-in-curses-or-sdl[/url]
qemu:[url]http://wiki.qemu.org/Testing[/url]
参考:[url]http://blog.chinaunix.net/uid-20729583-id-1884617.html[/url]
[url]http://blog.chinaunix.net/uid-26872853-id-3428938.html[/url]
这里有版本相关的问题
参考极客范:[url]http://www.geekfan.net/8663/[/url]
<think>嗯,用户现在想了解如何学习Linux内核协议栈。首先,我需要确定用户的基础水平和学习目标。可能用户是刚开始接触Linux内核,或者已经有了一定的操作系统和网络基础,想要深入理解协议栈的实现。 接下来,用户的需求可能不仅仅是理论上的学习,而是希望有实践的方法,比如如何阅读代码、调试或者进行实际开发。因此,回答需要涵盖理论和实践的结合。 然后,我应该考虑学习路径的结构。通常,学习内核协议栈需要分步骤进行,从基础知识到深入分析,再到实践和社区参与。需要推荐一些经典书籍,比如《Linux内核设计与实现》和《深入理解Linux网络技术内藏》,这些书籍是学习内核的重要资源。 另外,用户可能对具体的代码结构和工具不熟悉,所以需要指出关键的代码目录,如net/目录下的核心代码,以及调试工具如ftrace、systemtap等。这部分需要详细说明,但也要注意不要过于技术化,让初学者也能理解。 还需要考虑到用户可能遇到的困难,比如内核代码的复杂性,调试的难度,因此建议从简单模块入手,逐步深入。同时,参与开源社区和实际项目可以提升实战能力,这也是用户可能需要的建议。 最后,要确保回答结构清晰,分点列出,帮助用户逐步解决问题。同时提醒用户保持耐心,持续实践,因为学习内核协议栈是一个长期的过程。</think>学习Linux内核协议栈需要结合**网络协议理论**和**内核代码实践**,以下为分阶段学习路线,配合关键代码模块与工具使用建议: --- ### 一、前置知识储备 #### 1. **网络协议基础** - **必学协议栈**:TCP/IP四层模型(链路层/网络层/传输层/应用层) - 链路层:ARP协议、MAC帧结构(需理解`struct ethhdr`) - 网络层:IP协议(RFC 791)、ICMP报文(`net/ipv4/icmp.c`) - 传输层:TCP三次握手(`net/ipv4/tcp_input.c`中`tcp_rcv_state_process`函数)、UDP无连接特性 - **推荐书籍**: - 《TCP/IP详解 卷1:协议》(重点第2-24章) - 《计算机网络:自顶向下方法》 #### 2. **Linux内核基础** - **核心机制**: - 进程调度与软中断(`net_rx_action`在`net/core/dev.c`) - 内存管理(`sk_buff`结构体在`include/linux/skbuff.h`) - 内核同步机制(自旋锁、RCU在网络栈的应用) - **入门书籍**: -Linux内核设计与实现》(Robert Love) - 《深入理解Linux网络技术内幕》(重点讲解网络子系统) --- ### 二、内核协议栈核心代码分析 #### 1. **代码结构导航** - **关键目录**: ```bash net/ # 核心网络栈 ├── core/ # 通用层(sk_buff处理、邻居子系统) ├── ipv4/ # IPv4协议实现(TCP/UDP/ICMP) ├── ipv6/ # IPv6协议栈 └── netfilter/ # Netfilter框架(iptables底层) ``` - **核心数据结构**: - `struct sock`(套接字抽象,`include/net/sock.h`) - `struct net_device`(网卡设备,`include/linux/netdevice.h`) #### 2. **数据流跟踪** - **接收路径**(以TCP包为例): ```c // 驱动层接收(网卡中断) netif_receive_skb() → ip_rcv() → tcp_v4_rcv() → tcp_rcv_state_process() ``` - **发送路径**: ```c sock_sendmsg() → inet_sendmsg() → tcp_sendmsg() → ip_queue_xmit() ``` #### 3. **调试工具** - **动态追踪**: - `ftrace`:跟踪内核函数调用(`echo function > /sys/kernel/debug/tracing/current_tracer`) - `systemtap`:编写脚本监控`sk_buff`生命周期 - **静态分析**: - `cscope` + `vim/emacs`:代码跳转(生成索引:`cscope -R -b -q`) - LXR在线代码阅读器(如https://elixir.bootlin.com/) --- ### 三、实战进阶方法 #### 1. **实验环境搭建** - **推荐配置**: - 内核版本:选择LTS版本(如5.15.x),通过`git clone git://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git`获取 - 调试环境:QEMU + GDB调试内核(需启用`CONFIG_DEBUG_INFO`) #### 2. **动手实践项目** - **难度分级**: - 初级:编写Netfilter模块统计TCP连接数(HOOK`NF_INET_LOCAL_IN`) - 中级:修改拥塞控制算法(实现`struct tcp_congestion_ops`) - 高级:添加自定义协议(在`net/protocols`注册新协议) #### 3. **性能优化案例** - **典型问题**: - 零拷贝优化:`sendfile()`系统调用与`DMA`机制 - 多队列网卡:`RPS`(Receive Packet Steering)配置 - **参考论文**: - 《The BSD Packet Filter: A New Architecture for User-level Packet Capture》 - 《Scalability of the Linux Kernel Networking Stack》 --- ### 四、社区与资源 1. **官方资源**: - [Kernel Documentation](https://www.kernel.org/doc/html/latest/)(重点阅读`networking`章节) - [Linux内核邮件列表](https://lore.kernel.org/lkml/)(关注netdev子列表) 2. **开源项目参考**: - DPDK(用户态协议栈对比学习) - Cilium(eBPF在网络栈的应用) --- ### 学习建议 - **从简单模块切入**:优先研究ICMP协议实现(代码量少且逻辑清晰) - **结合Wireshark抓包**:对比理论模型与实际代码行为 - **参与内核网络子系统的Bug修复**(通过`git log net/`查看近期补丁) 通过**理论→代码→实验→优化**的循环学习,逐步掌握协议栈全貌。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值