安装

gcore扩展模块在crash论坛网站(http://people.redhat.com/anderson/)的扩展模块发布页(http://people.redhat.com/anderson/extensions.html)上可以找到。

crash的详细安装方法在HACK#59中已经介绍。创建gcore扩展模块时需要将源代码解压缩到扩展模块用的extensions目录下。


$cd extensions

$tar xf~/src/gcore.tar.bz2

$cd../

$make extensions


创建处理程序如果正常结束,在extensions目录下就会生成gcore.so文件。


$ls-hld./extensions/gcore.so

-rwxr-xr-x 1 root root 235K 2011-05-28 18:02./extensions/gcore.so


基本使用方法

启动crash命令后,将gcore扩展模块安装到crash中,提取用户模式进程的进程核心转储,使用gdb显示提取的进程核心转储的回溯译[1]。crash启动后安装gcore.so。安装时使用extend命令。


$pwd

./crash-5.1.5/

$./crash vmcore vmlinux

……

crash>extend gcore.so

./extensions/gcore.so:shared object loaded


如果安装成功,就会添加gcore命令。可以使用help命令进行确认。


crash>help|grep gcore

bt gcore net set vtop


gcore命令的语法如下所示。


gcore[-v<冗长级别>][-f<过滤器级别>][<PID>|<任务地址>]*


向gcore命令指定想要获取进程核心转储的用户模式进程的PID或任务地址。不指定时,就是作为crash命令对象的进程上下文。

下面尝试使用gcore生成进程核心转储。使用ps命令找到获取进程核心转储的用户进程的PID。本次将udevd进程作为对象。


crash>ps

PID PPID CPU TASK ST%MEM VSZ RSS COMM

……

369 1 0 ffff88003c701730 IN 0.2 17524 1692 udevd


最左边的项目PID中显示PID,从左边开始第4个项目TASK显示任务地址。crash进程的PID为369,任务地址为ffff88003c701730。

下面尝试使用gcore命令。这里指定的是udevd进程的PID 369。


crash>gcore 369

WARNING:page fault at 7f4a5fc98000

……<snip>……

WARNING:page fault at 7fffc3d6c000

Saved core.369.udevd

crash>ls-hl./core.369.udevd

-rw———-1 hat hat 18M Jul 4 20:23./core.369.udevd


gcore命令的处理顺利结束,生成了进程核心转储文件core.369.udevd。gcore生成的进程核心转储的文件名为如下格式。


core.<PID>.<执行文件名>


在gcore命令执行过程中,显示说明页面错误的下列信息。


gcore:WARNING:page fault at<地址>


用户内存空间中的下列页面区域不能从crash命令得到。

·一次也没有分配内存的区域

·分配过内存,但位于当前pageout的区域

gcore命令对于这样的内存区域,都写入0来生成核心转储。为了让用户能够意识到这一点,将按照标准输出下列信息。

除页面错误以外,还可以显示gcore命令处理的进展信息。如表7-17所示,使用-v选项向gcore命令指定要显示的信息。例如,如果认为不需要上述页面错误的通知信息时,可以在-v选项中指定0,来抑制信息的显示。


crash>gcore-v 0 369

Saved core.369.udevd

crash>


gcore命令中也有与核心转储过滤器对应的功能,在这里没有用到。在-f选项中指定位掩码的值。能够过滤的内存种类与核心转储过滤器相同。过滤的内存种类和-f选项的值的对应关系如表7-18所示。

安装 - 图1

安装 - 图2

下面使用gdb来显示该进程核心转储的回溯。


$gdb/usr/lib/debug/sbin/udevd.debug./core.369.udevd(gdb)bt

0 0x00007f4a60398258 in__poll(fds=0x7f4a610da020,nfds=5,timeout=-1)at../sysdeps/unix/sysv/linux/poll.c:83

1 0x00007f4a60ebb483 in main(argc=<optimized out>,argv=<optimized out>)at udev/udevd.c:1406


从回溯的信息可以看出,提取内核崩溃转储时,udevd进程执行了函数__poll内的地址0x00007f4a60398258。从函数名称可以看出,udevd进程当时正在执行轮询(polling)。如果使用gdb命令的x选项对这个地址进行反汇编,可以发现插入了执行系统调用的命令syscall的下列命令。


(gdb)x/2i 0x00007f4a60398256

0x7f4a60398256<__poll+22>:syscall

=>0x7f4a60398258<__poll+24>:cmp$0xfffffffffffff000,%rax


使用syscall命令执行系统调用时,使用RAX寄存器指定系统调用编号。在把模式转移到内核时的寄存器值可以使用gcore命令的info register选项来找出。


(gdb)info register

rax 0x7 7

rbx 0x7f4a61a61ec0 139957442584256

rcx 0xffffffffffffffff-1

rdx 0xffffffffffffffff-1

rsi 0x5 5

rdi 0x7f4a610da020 139957432590368

rbp 0x0 0x0

rsp 0x7fffc3d739e0 0x7fffc3d739e0

r8 0x7f4a60655230 139957421560368

r9 0x0 0

r10 0x0 0

r11 0x246 582

r12 0x7f4a61a03010 139957442195472

r13 0x7f4a610da130 139957432590640

……


如上所示,RAX的值就是x86_64架构中poll系统调用的系统调用编号。可以看出udevd进程正在等待轮询的事件。

[1]回溯对应的英文是back trace。