内核调试--VFS路径名查找
经过一个月对Linux vfs层的代码进行阅读总算有点眉目,今天这些天的心得写到这里,希望有大侠能够指正我的理解误区,现在这里拜谢了。
这篇笔记主要是记录在Linux2.6.37 的UML模式中调试vfs中的路径名查找的过程
1.搭建UML环境,
a.至少需要一个内核,文件系统(你可以手工制作文件系统)
我的内核采用Linux 2.6.37 文件系统从网上下载的现成的叫DSLxxx具体叫什么我忘了,因为下载下来我把它改了一个名字
b.这一部分至关重要,是后面的调试关键,我在这里也费了几乎一个星期的时间,废话少说,先介绍难点。最困难的不是选择编译选项而是内核在编译的时候使用优化默认O2,导致一些代码的次序改变,单步的时候乱跳,让你不知其所以然。我们先看看一个文件 内核文件夹下的scripts/Makefile.build 前几行
我们不能关闭内核优化选项,不然需要修改很多代码,我们在我们需要的调试的的模块部分
让内核去掉优化,我们可以这样做。我要对文件系统进行调试,打开fs/Makefile 在文件开头加入 EXTRA_CFLAGS += -O0.文件如下
接下来 执行
make menuconfig ARCH=um
配置内核选项,注意打开内核的调试选项,(在kernel hacking --->kernel debug--->compile ...debug info 记得不是很清楚)
make ARCH=um
在内核目录中会生成一个叫 linux可执行文件,接下来可以新建一个文件夹,把内核源码目录下生成的linux 文件和根文件系统放到一起如下
2.调试内核。
a.在调试内核的时候你可以选择多种方法调试,一般使用下面命令
gdb ./linux ubda=root_fs(ubda=你的文件系统的路径)
上述调试方法会有一个问题,当你的内核完全启动完毕,即启动到命令行的时候,你无法产生断点,除非你在执行gdb >run命令前,在某一个函数前打了断点,但是在启动过程中,可能会引起无数的断点影响调试效果。
最开始我准备调试link_path_walk函数,在这里打了一个断点,启动的时候内核会查找文件,导致断点成千上万,我禁止断点后,启动到命令行了,无法使gdb产生断点。导致调试转了很大的弯路。
现在使用另外一种方法调试,gdb 调试进程
首先启动要调试的内核,对于上面,执行下面的命令
./linux ubda=root_fs 效果如下图
这篇笔记主要是记录在Linux2.6.37 的UML模式中调试vfs中的路径名查找的过程
1.搭建UML环境,
a.至少需要一个内核,文件系统(你可以手工制作文件系统)
我的内核采用Linux 2.6.37 文件系统从网上下载的现成的叫DSLxxx具体叫什么我忘了,因为下载下来我把它改了一个名字
b.这一部分至关重要,是后面的调试关键,我在这里也费了几乎一个星期的时间,废话少说,先介绍难点。最困难的不是选择编译选项而是内核在编译的时候使用优化默认O2,导致一些代码的次序改变,单步的时候乱跳,让你不知其所以然。我们先看看一个文件 内核文件夹下的scripts/Makefile.build 前几行
- # ==========================================================================
- # Building
- # ==========================================================================
- src := $(obj)
- PHONY := __build
- __build:
- # Init all relevant variables used in kbuild files so
- # 1) they have correct type
- # 2) they do not inherit any value from the environment
- obj-y :=
- obj-m :=
- lib-y :=
- lib-m :=
- always :=
- targets :=
- subdir-y :=
- subdir-m :=
- EXTRA_AFLAGS :=
- EXTRA_CFLAGS :=
- EXTRA_CPPFLAGS :=
- EXTRA_LDFLAGS :=
- asflags-y :=
- ………………
我们不能关闭内核优化选项,不然需要修改很多代码,我们在我们需要的调试的的模块部分
让内核去掉优化,我们可以这样做。我要对文件系统进行调试,打开fs/Makefile 在文件开头加入 EXTRA_CFLAGS += -O0.文件如下
1.png (19.17 KB, 下载次数: 72)
接下来 执行
make menuconfig ARCH=um
配置内核选项,注意打开内核的调试选项,(在kernel hacking --->kernel debug--->compile ...debug info 记得不是很清楚)
make ARCH=um
在内核目录中会生成一个叫 linux可执行文件,接下来可以新建一个文件夹,把内核源码目录下生成的linux 文件和根文件系统放到一起如下
2.png (20.62 KB, 下载次数: 21)
2.调试内核。
a.在调试内核的时候你可以选择多种方法调试,一般使用下面命令
gdb ./linux ubda=root_fs(ubda=你的文件系统的路径)
上述调试方法会有一个问题,当你的内核完全启动完毕,即启动到命令行的时候,你无法产生断点,除非你在执行gdb >run命令前,在某一个函数前打了断点,但是在启动过程中,可能会引起无数的断点影响调试效果。
最开始我准备调试link_path_walk函数,在这里打了一个断点,启动的时候内核会查找文件,导致断点成千上万,我禁止断点后,启动到命令行了,无法使gdb产生断点。导致调试转了很大的弯路。
现在使用另外一种方法调试,gdb 调试进程
首先启动要调试的内核,对于上面,执行下面的命令
./linux ubda=root_fs 效果如下图
3.png (44.12 KB, 下载次数: 20)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
本帖最后由 jjinl 于 2011-06-17 14:19 编辑
其次查找上述UML的进程PID如下图,注意需要pid最小的那一个
4.png (17.23 KB, 下载次数: 29)
下载附件
2011-06-17 14:13 上传
接着使用gdb调试,命令:”gdb program xxx”其中xxx为名为linux的进程中pid最小的pid号,操作如下图
5.png (52.29 KB, 下载次数: 19)
下载附件
2011-06-17 14:13 上传
现在运行UML的那个终端已被停止,我们在link_path_walk打一个断点,如下图
6.png (33.26 KB, 下载次数: 21)
下载附件
2011-06-17 14:14 上传
接下来在gdb中执行 continue,如下图
7.png (33 KB, 下载次数: 22)
下载附件
2011-06-17 14:14 上传
在上图中,他自动在link_path_walk停住,如果没有停住,先检查断点是否正确,你可以在uml中输入,例如ls命令,就会使之跑到这里
调试效果如下
8.png (42.46 KB, 下载次数: 19)
下载附件
2011-06-17 14:15 上传
9.png (55.33 KB, 下载次数: 18)
下载附件
2011-06-17 14:15 上传
10.png (46.23 KB, 下载次数: 27)
下载附件
2011-06-17 14:15 上传
下个星期补充....link_path_walk函数流程
回复 1# jjinl
感谢 LZ 分享。
我们主要调试的函数是在fs/namei.c 的817行的link_path_walk,,在调试之前,为了便于说明一些情况,我们对这个源码进行小幅度的修改,输出当前进程的task_struct,代码如下
1.png (18.82 KB, 下载次数: 25)
下载附件
2011-06-20 11:39 上传
接下来我们重点讲述这个函数,
2.png (32.67 KB, 下载次数: 17)
下载附件
2011-06-20 11:39 上传
上述一个断点产生在link_path_walk上,在执行路径名到inode转换前,需要对相关结构进行初始化,包括查找的起始路径,查找的标志,这些信息都暂时存放在struct nameidate *nd中,这个结果内容如下
复制代码接下来我们打印一下,看看nd中到底有什么
3.png (38.53 KB, 下载次数: 25)
下载附件
2011-06-20 11:39 上传
我们知道要查找的文件是“/dev/initctl”,是绝对路径的查找,上图中第一部分是nd中的内容。其中
nd->path->mnt =0xa0524e0
nd->path->dentry =0x9c49214
pcur->fs->pwd->mnt =0xa0524e0
pcur->fs->pwd->dentry =0x9c49214
pcur->fs->root->mnt =0xa0524e0
pcur->fs->root->dentry =0x9c49214
$esp =0xa05cb4c
Pcur =0xa05bb20
有没有发现nd中的path的内容和当前的进程的fs->pwd和root是一样的,这是这样的在查找之前对判断路径名的第一个字母如果是”/”,则把当前进程的fs->root赋值给nd->path;如果是”.”则把当前进程的fs->pwd赋值给nd->path,因为我的系统当前在根目录下所以会有,fs->root=fs->pwd.最后我打印出寄存器esp的内容和当前函数中的局部变量pcur的地址如下图。大家有没有发现esp和当前函数的局部变量的关系,当前处于内核态,esp指向内核栈,这些局部变量使用当前进程的内核栈,内核栈的很小,使用的时候应当注意
4.png (14.98 KB, 下载次数: 19)
下载附件
2011-06-20 11:39 上传
言归正传,在826行处理路径名最前面的任何“/”接下来准备取出第一个路径分量,在inode中查找对应的文件(文件夹)如下图,831行,
5.png (27.21 KB, 下载次数: 22)
下载附件
2011-06-20 11:39 上传
对取出来的路径分量进行散列计算,接下来判断路径分量中的路径名是否为特殊的文件名如”.”,”..”
6.png (22.56 KB, 下载次数: 18)
下载附件
2011-06-20 11:39 上传
838行的do_lookup查找对应this这个字符串在nd->path中对应的路径分量,结果放在next中,接着888行取出对应路径分量的inode
.........
good
强烈支持一下
好文,顶。
最近弄了个UML,流程和Lz一样。但是每次只能成功启动一次。启动进入shell 后我init 0关机后。再次启动
./linux ubda=root_fs
就挂了,出错如下,帮忙看看,谢谢
[img]EXT3-fs (ubda): error: couldn't mount because of unsupported optional features (240)
EXT2-fs (ubda): error: couldn't mount because of unsupported optional features (240)
EXT4-fs (ubda): mounted filesystem with ordered data mode. Opts: (null)
VFS: Mounted root (ext4 filesystem) readonly on device 98:0.
Welcome to Fedora
Starting udev: udevd[232]: failed to create queue file: No such file or directory
udevd[232]: error creating queue file
error sending message: Connection refused
udevadm[235]: error sending message: Connection refused
[FAILED]
Setting hostname localhost: [ OK ]
Checking filesystems
Checking all file systems.
[ OK ]
Remounting root filesystem in read-write mode: mount: can't find / in /etc/fstab or /etc/mtab
[FAILED]
mount: can't find / in /etc/fstab or /etc/mtab
Mounting local filesystems: [ OK ]
chmod: changing permissions of `/var/lib/random-seed': Read-only file system
rm: cannot remove `/var/run/utmp': Read-only file system
rm: cannot remove `/var/run/cron.reboot': Read-only file system
/etc/rc.d/rc.sysinit: line 593: /var/run/utmp: Read-only file system
touch: cannot touch `/var/log/wtmp': Read-only file system
touch: cannot touch `/var/log/btmp': Read-only file system
chgrp: changing group of `/var/run/utmp': Read-only file system
chgrp: changing group of `/var/log/wtmp': Read-only file system
chgrp: changing group of `/var/log/btmp': Read-only file system
chmod: changing permissions of `/var/run/utmp': Read-only file system
chmod: changing permissions of `/var/log/wtmp': Read-only file system
chmod: changing permissions of `/var/log/btmp': Read-only file system
rm: cannot remove `/tmp/.ICE-unix': Read-only file system
chown: changing ownership of `/tmp/.ICE-unix': Read-only file system
Enabling /etc/fstab swaps: [ OK ]
modprobe: FATAL: Could not load /lib/modules/2.6.38-124329-gebcb904/modules.dep: No such file or directory
mv: cannot move `/var/log/dmesg' to `/var/log/dmesg.old': Read-only file system
/etc/rc.d/rc.sysinit: line 651: /var/log/dmesg: Read-only file system
modprobe: FATAL: Could not load /lib/modules/2.6.38-124329-gebcb904/modules.dep: No such file or directory
Entering non-interactive startup
Starting auditd: modprobe: FATAL: Could not load /lib/modules/2.6.38-124329-gebcb904/modules.dep: No such file or directory
[FAILED]
Starting system logger: Can't open or create /var/run/syslogd.pid.
Can't write pid.
[img][/img][/img]
有时间我也搞个UML试试,才听说这个东西
回复 7# 懂医术的厨师
你好,请问下以上帖子中你提及的问题解决了吗?如何解决的啊,我也遇到了相似的问题,还望交流下,谢谢~!