免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8145 | 回复: 8
打印 上一主题 下一主题

内核调试--VFS路径名查找 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-06-17 14:12 |只看该作者 |倒序浏览
经过一个月对Linux vfs层的代码进行阅读总算有点眉目,今天这些天的心得写到这里,希望有大侠能够指正我的理解误区,现在这里拜谢了。
这篇笔记主要是记录在Linux2.6.37 的UML模式中调试vfs中的路径名查找的过程
1.搭建UML环境,
a.至少需要一个内核,文件系统(你可以手工制作文件系统)
我的内核采用Linux 2.6.37 文件系统从网上下载的现成的叫DSLxxx具体叫什么我忘了,因为下载下来我把它改了一个名字
b.这一部分至关重要,是后面的调试关键,我在这里也费了几乎一个星期的时间,废话少说,先介绍难点。最困难的不是选择编译选项而是内核在编译的时候使用优化默认O2,导致一些代码的次序改变,单步的时候乱跳,让你不知其所以然。我们先看看一个文件 内核文件夹下的scripts/Makefile.build 前几行
  1. # ==========================================================================
  2. # Building
  3. # ==========================================================================

  4. src := $(obj)

  5. PHONY := __build
  6. __build:

  7. # Init all relevant variables used in kbuild files so
  8. # 1) they have correct type
  9. # 2) they do not inherit any value from the environment
  10. obj-y :=
  11. obj-m :=
  12. lib-y :=
  13. lib-m :=
  14. always :=
  15. targets :=
  16. subdir-y :=
  17. subdir-m :=
  18. EXTRA_AFLAGS   :=
  19. EXTRA_CFLAGS   :=
  20. EXTRA_CPPFLAGS :=
  21. EXTRA_LDFLAGS  :=
  22. asflags-y  :=
  23. ………………
复制代码
看到EXTRA_CFLAGS这个,具体是干啥,可以自己去查查
我们不能关闭内核优化选项,不然需要修改很多代码,我们在我们需要的调试的的模块部分
让内核去掉优化,我们可以这样做。我要对文件系统进行调试,打开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  效果如下图

评分

参与人数 1可用积分 +8 收起 理由
Godbach + 8 感谢分享

查看全部评分

论坛徽章:
0
2 [报告]
发表于 2011-06-17 14:15 |只看该作者
本帖最后由 jjinl 于 2011-06-17 14:19 编辑

其次查找上述UML的进程PID如下图,注意需要pid最小的那一个

接着使用gdb调试,命令:”gdb program xxx”其中xxx为名为linux的进程中pid最小的pid号,操作如下图

现在运行UML的那个终端已被停止,我们在link_path_walk打一个断点,如下图

接下来在gdb中执行 continue,如下图

在上图中,他自动在link_path_walk停住,如果没有停住,先检查断点是否正确,你可以在uml中输入,例如ls命令,就会使之跑到这里
调试效果如下



下个星期补充....link_path_walk函数流程

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
3 [报告]
发表于 2011-06-17 14:44 |只看该作者
回复 1# jjinl

感谢 LZ 分享。

论坛徽章:
0
4 [报告]
发表于 2011-06-20 11:42 |只看该作者
我们主要调试的函数是在fs/namei.c 的817行的link_path_walk,,在调试之前,为了便于说明一些情况,我们对这个源码进行小幅度的修改,输出当前进程的task_struct,代码如下

接下来我们重点讲述这个函数,

上述一个断点产生在link_path_walk上,在执行路径名到inode转换前,需要对相关结构进行初始化,包括查找的起始路径,查找的标志,这些信息都暂时存放在struct nameidate *nd中,这个结果内容如下
  1. struct nameidata {
  2.         struct path        path;
  3.         struct qstr        last;
  4.         struct path        root;
  5.         unsigned int        flags;
  6.         int                last_type;
  7.         unsigned        depth;
  8.         char *saved_names[MAX_NESTED_LINKS + 1];

  9.         /* Intent data */
  10.         union {
  11.                 struct open_intent open;
  12.         } intent;
  13. };
复制代码
接下来我们打印一下,看看nd中到底有什么

我们知道要查找的文件是“/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指向内核栈,这些局部变量使用当前进程的内核栈,内核栈的很小,使用的时候应当注意

言归正传,在826行处理路径名最前面的任何“/”接下来准备取出第一个路径分量,在inode中查找对应的文件(文件夹)如下图,831行,

对取出来的路径分量进行散列计算,接下来判断路径分量中的路径名是否为特殊的文件名如”.”,”..”

838行的do_lookup查找对应this这个字符串在nd->path中对应的路径分量,结果放在next中,接着888行取出对应路径分量的inode
.........

论坛徽章:
0
5 [报告]
发表于 2011-06-22 09:49 |只看该作者
good

论坛徽章:
13
巨蟹座
日期:2013-10-30 18:29:4115-16赛季CBA联赛之青岛
日期:2019-01-04 17:30:1015-16赛季CBA联赛之天津
日期:2016-03-08 10:30:1715-16赛季CBA联赛之天津
日期:2015-12-10 15:56:452015年亚洲杯之约旦
日期:2015-03-09 16:29:36双鱼座
日期:2014-11-27 17:17:20寅虎
日期:2014-11-18 13:55:12双子座
日期:2014-03-31 15:41:32狮子座
日期:2014-03-14 11:23:24狮子座
日期:2014-02-19 16:30:12午马
日期:2013-11-04 23:22:31卯兔
日期:2013-10-30 19:51:15
6 [报告]
发表于 2011-06-22 12:03 |只看该作者
强烈支持一下

论坛徽章:
0
7 [报告]
发表于 2011-06-24 13:42 |只看该作者
好文,顶。
最近弄了个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]

论坛徽章:
0
8 [报告]
发表于 2011-06-24 14:03 |只看该作者
有时间我也搞个UML试试,才听说这个东西

论坛徽章:
1
2015年辞旧岁徽章
日期:2015-03-03 16:54:15
9 [报告]
发表于 2015-08-21 14:55 |只看该作者
回复 7# 懂医术的厨师

你好,请问下以上帖子中你提及的问题解决了吗?如何解决的啊,我也遇到了相似的问题,还望交流下,谢谢~!
   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP