内核转储的设置方法

关于内核转储的设置方法

1. 内核转储作用

(1) 内核转储的最大好处是能够保存问题发生时的状态。

(2) 只要有可执行文件和内核转储,就可以知道进程当时的状态。

(3) 只要获取内核转储,那么即使没有复现环境,也能调试。

2. 启用内核转储

1.1 查看内核转储是否有效

在终端中输入以下命令,查看内核转储是否有效。

#ulimit -c

0

-c 表示内核转储文件的大小限制,现在显示为零,表示不能用。

可以改为1G

#ulimit -c 1073741824

也可以改为无限制

#ulimit -c unlimited

2.2 测试一个例子

例子的源代码:

#include <stdio.h>

int main(void)

{

int *a = NULL;

*a = 0x1;

return 0;

}

把以上源代码,写成一个a.c文件后,编译a.c文件产生一个a.out的可执行文件:

#gcc -g a.c -o a.out

修改a.out文件的权限后,执行它:

#./a.out

就会显示:

Segmentation fault(core dump)

这表示在当前目录下, 已经生成了a.out对应的内核转储文件。

注意:后面带有(core dump), 才说明转储文件成功生成了。

#file core*

core:ELF 64-bit LSB core file x86-64, version 1(SYSV), SVR4-style, from ‘./a.out‘

coreDump: UTF-8 Unicode C program text

要用GDB调试内核转储文件,应该使用以下方式启动GDB:

#gdb -c ./*.core ./a.out

GNU gdb (GDB) 7.1-Ubuntu

...

Core was generated by ‘./a.out‘.

Program terminated with signal 11, Segmentation fault.

#0 0x00000000004004dc in main() at a.c:6

6 *a =0x1;

a.c的第6行收到了11号信号。用GDB的list命令可以查看附近的源代码。

(gdb) l 5

1            #include <stdio.h>

2

3            int main(void)

4            {

5                   int *a = NULL;

6                   *a = 0x1;

7                   return 0;

8            }

这里默认都是当前目录,也可以给core 和a.out 指定路径

到这里测试完成!

2.3 永久生效的办法

上面所述的方法,只是在当前shell中生效,重启之后,就不再有效了。永久生效的办法是:

#vi /etc/profile 然后,在profile中添加:

ulimit -c 1073741824

(但是,若将产生的转储文件大小大于该数字时,将不会产生转储文件)

或者

ulimit -c unlimited

这样重启机器后生效了。 或者, 使用source命令使之马上生效。

#source /etc/profile

3. 指定内核转储的文件名和目录

缺省情况下,内核在coredump时所产生的core文件放在与该程序相同的目录中,并且文件名固定为core。很显然,如果有多个程序产生core文件,或者同一个程序多次崩溃,就会重复覆盖同一个core文件。

我们可以通过修改kernel的参数,指定内核转储所生成的core文件的路径和文件名。

可以通过在/etc/sysctl.conf文件中,对sysctl变量kernel.core_pattern的设置。

#vi /etc/sysctl.conf 然后,在sysctl.conf文件中添加下面两句话:

kernel.core_pattern = /var/core/core_%e_%p

kernel.core_uses_pid = 0

保存后退出。

需要说明的是, /proc/sys/kernel/core_uses_pid。如果这个文件的内容被配置成1,即使core_pattern中没有设置%p,最后生成的core dump文件名仍会加上进程ID。

这里%e, %p分别表示:

%c 转储文件的大小上限

%e 所dump的文件名

%g 所dump的进程的实际组ID

%h 主机名

%p 所dump的进程PID

%s 导致本次coredump的信号

%t 转储时刻(由1970年1月1日起计的秒数)

%u 所dump进程的实际用户ID

可以使用以下命令,使修改结果马上生效。

#sysctl –p /etc/sysctl.conf

请在/var目录下先建立core文件夹,然后执行a.out程序,就会在/var/core/下产生以指定格式命名的内核转储文件。查看转储文件的情况:

#ls /var/core

core_a.out_2834

4. 手动强制某个进程产生core dump的方法(尝试)

当某些程序发生crash时,对应进程会产生coredump文件。通过这个coredump文件,开发人员可以找到bug的原因。但是coredump的产生,大都是因为程序crash了。

而有些bug是不会导致程序crash的,比如死锁,这时程序已经不正常了,可是却没有coredump产生。如果环境又不允许gdb调试,难道我们就束手无策了吗?

针对以上这种情况,一般情况下,对于这样的进程可以利用 watchdog监控它们,当发现这些进程很长时间没有更新其heartbeat时,可以给这些进程发送可以导致其产生coredump的信号。根据 linux的信号默认的处理行为,SIGQUIT,SIGABRT, SIGFPE和SIGSEGV都可以让该进程产生coredump文件。这样我们可以通过coredump来得知死锁是否发生。 当然, 如果进程添加了这些信号的处理函数,那么就不会产生coredump了。不过,对于SIGQUIT, SIGABRT, SIGFPE, SIGSEGV,有谁会为它们加上信号处理函数呢。

还有一种情况,进程并没有死锁或者block在某个位置, 但是我们需要在某个指定位置进行调试,获取某些变量或者其它信息。但是,有可能是客户环境或者生产环境,不允许我们进行长时间的检测。那么,我们就需要通 过coredump来获得进程在运行到该点时的快照。 这个时候,可以利用gdb来手工产生coredump。在attach上这个进程时,在指定位置打上断点,当断点触发时,使用gdb的命令gcore,可 以立即产生一个coredump。 这样,我们就拿到了这个位置的进程快照。

1.寻找您要发送信号的进程ID,

# ps -ef  | grep qemu

root      3207  3206 44 10:32 pts/1    00:00:18 /usr/local/bin/qemu-system-x86

得出 qemu-system-x86的 PID号是3207

2.使用kill(1)去发送信号。

# /bin/kill -s QUIT 3207

发送其他的信号也很相似, 只要在命令行中替换QUIT 为ABRT,TERM 或 KILL 就行了

重要提示: 在系统上随意杀死进程是一个坏主意,特别是init(8),它的PID是1,它非常特殊。 可以运行 /bin/kill -s KILL 1 命令来让系统迅速关机。  当您按下 Return (回车)键之前,一定要 详细检查您运行 kill(1) 时所指定的参数。

5 使用core dump进行调试

在Linux下遇到“段错误”(segmentation fault),如果段错误发生在服务器端,而服务器端要继续工作,不允许调试,这时“内核转储(core dump)”就派上了用场,可以把生成的内核转储复制到本地进行调试。

首先,按照上面的永久生效方法,在服务器上进行相应设置。 然后程序在崩溃时,就会在程序所在目录(或自己指定的目录)生成一个core文件,把这个core文件拷到本地(最好与该进程对应的可执行文件放到同一个目录,若不然,在gdb时指出路径也可以)。

具体方法如下:

方法一:

输入命令 #gdb <程序可执行文件> <coredump转储文件>

例如:

# gdb /usr/local/bin/qemu-system-x86_64  /var/core/core-3207-qemu-system-x86

然后,在(gdb)提示符后输入 l,  会显示main主函数

方法二:

(1) 在终端输入命令# gdb [-c] <coredump文件>,

例如: gdb -c /var/core/core-3207-qemu-system-x86

(2)然后,在(gdb)提示符后输入file <可执行程序>

例如:(gdb) file  /usr/local/bin/qemu-system-x86_64

(3) 这时就可以用backtrace/thread等命令查看当时的错误了,就像程序在本地执行到崩溃点一样

或者用where回车, 也可以显示程序在哪一行当掉的

5. 启用整个系统的内核转储

(未完待续......)

(4.1) 编辑/etc/profile, 开启登录到系统的所有用户的内核转储功能

首先,看看用的是个什么机器:

# uname –a

Linux ubuntu240 2.6.32-21-server #32-Ubuntu SMP Fri Apr 16 09:17:34 UTC 2010 x86_64 GNU/Linux

其次,再查看一些默认参数,若core file size是0,即使程序出错时,也不会产生core文件。

# ulimit -a

core file size              (blocks, -c) unlimited

data seg size              (kbytes, -d) unlimited

scheduling priority               (-e) 20

file size                  (blocks, -f) unlimited

pending signals                  (-i) 16382

max locked memory        (kbytes, -l) 64

max memory size         (kbytes, -m) unlimited

open files                      (-n) 1024

pipe size              (512 bytes, -p) 8

POSIX message queues     (bytes, -q) 819200

real-time priority                (-r) 0

stack size                (kbytes, -s) 8192

cpu time                (seconds, -t) unlimited

max user processes              (-u) unlimited

virtual memory           (kbytes, -v) unlimited

file locks                      (-x) unlimited

查看栈信息

当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用GDB命令来查看当前的栈中的信息。

下面是一些查看函数调用栈信息的GDB命令:

backtrace
bt

打印当前的函数调用栈的所有信息。如:

(gdb) bt
#0 func (n=250) at tst.c:6
#1 0x08048524 in main (argc=1, argv=0xbffff674) at tst.c:30
#2 0x400409ed in __libc_start_main () from /lib/libc.so.6

从上可以看出函数的调用栈信息:__libc_start_main --> main() --> func()

backtrace
bt

n是一个正整数,表示只打印栈顶上n层的栈信息。

backtrace <-n>
bt <-n>

-n表一个负整数,表示只打印栈底下n层的栈信息。

如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。

frame
f

n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。

up

表示向栈的上面移动n层,可以不打n,表示向上移动一层。

down

表示向栈的下面移动n层,可以不打n,表示向下移动一层。

上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:

select-frame 对应于 frame 命令。
up-silently 对应于 up 命令。
down-silently 对应于 down 命令。

查看当前栈层的信息,你可以用以下GDB命令:

frame 或 f

会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。

info frame
info f

这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。如:

(gdb) info f
Stack level 0, frame at 0xbffff5d4:
eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
called by frame at 0xbffff60c
source language c.
Arglist at 0xbffff5d4, args: n=250
Locals at 0xbffff5d4, Previous frame‘s sp is 0x0
Saved registers:
ebp at 0xbffff5d4, eip at 0xbffff5d8

info args
打印出当前函数的参数名及其值。

info locals
打印出当前函数中所有局部变量及其值。

info catch
打印出当前的函数中的异常处理信息。

时间: 2024-10-08 22:02:39

内核转储的设置方法的相关文章

关于内核转储(core dump)的设置方法

原作者:http://blog.csdn.net/wj_j2ee/article/details/7161586 1. 内核转储作用 (1) 内核转储的最大好处是能够保存问题发生时的状态. (2) 只要有可执行文件和内核转储,就可以知道进程当时的状态. (3) 只要获取内核转储,那么即使没有复现环境,也能调试. 2. 启用内核转储 1.1 查看内核转储是否有效 在终端中输入以下命令,查看内核转储是否有效. #ulimit -c 0 -c 表示内核转储文件的大小限制,现在显示为零,表示不能用. 可

arp防火墙分类及设置方法

有时候我们需要对电脑防火墙进行分类设置,对于一些与防火墙相冲突的软件,我们需要关闭防火墙,有时网络安全有问题时,我们又需要启用防火墙,还有一种既可以安装软件又启动防火墙的方法,具体操作如下. arp防火墙分类: 1.包过滤型防火墙:工作在TCP/IP层,根据tcp首部或ip首部数据进行判断,安全性较 低,效率较高: 1.简单包过滤: 2.带状态检测的包过滤: 1)NEW状态:-建立连接: 2)ESTABLISHED状态:-建立连接并传输数据: 3)INVALID状态(无法识别的状态): 4)RE

destoon6.0友情链接标签写法以及设置方法

最近自己喜欢上研究destoon内核,destoon个人认为是不错的架构,不仅在负载上,还是SEO的配置上都是不错的,所以近期都更新关于destoon方面的笔记,希望大家多多支持我!分享下近期学习的成果:http://zhimo.yuanzhumuban.cc/ 好了回归正题,上网找了很多,都没找到,今天在官方开发文档找到相关的,所以在此分享下自己改进的友情链接写法. <!--{tag("table=link&condition=status=3 and level>0 an

Ubuntu的内核转储工具【转】

转自:http://www.cnblogs.com/wwang/archive/2010/11/19/1881304.html 在我的上一篇博文<Linux内核的Oops>的最后介绍到一个Linux内核转储工具Kdump,这个工具可以在发生kernel panic时把现场dump到一个文件里,以供后续分析之用.本文主要介绍在Ubuntu下如何使用kdump. Kdump是一个通用的Linux内核转储工具,详细的用法说明可以参考这篇Kdump Tutorial.这篇教程洋洋洒洒几十页(链接里有p

ssh无密码登录设置方法以及出现问题 ECDSA host key 和IP地址对应的key不同的解决

最近在做hadoop,因为要求各主机之间的用户必须相同,且为方便远程登录,需配置无密码登录 先附上ssh无密码登录设置方法: 先生成密钥并配置无ssh无密码登录本机,输入命令: ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys 将文件拷贝到其他主机相同的文件夹内,输入命令: scp authorized_keys hostname1:~/.ssh/ scp autho

CListCtrl 扩展风格设置方法---SetExtendedStyle和ModifyStyleEx

想把ListCtr设置为整行高亮显示错误的方法为: 1 clistctrl.ModifyStyleEx(0,LVS_EX_FULLROWSELECT|LVS_EX_GRIDLINES); 正确的方法为: 1 DWORD dwStyle = clistctrl.GetExtendedStyle(); 2 dwStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES; 3 clistctrl.SetExtendedStyle(dwStyle); 那么,Modi

SQL Server 2008 阻止保存要求重新创建表的更改问题的设置方法

不是很理解为什么在2008中会加入阻止保存要求重新创建表的更改这个选项.症状表现为修改表结构的时候会"阻止"你.而且我遇到的情况是居然有的时候阻止你,有的时候不阻止你,摸不到头脑.SQL Server 2008“阻止保存要求重新创建表的更改”的错误的解决方案是本文我们主要要介绍的内容,情况是这样的:我们在用SQL Server 2008 建完表后,插入或修改任意列时,提示:当用户在在SQL Server 2008企业管理器中更改表结构时,必须要先删除原来的表,然后重新创建新表,才能完成

Wish新手必看 Wish Tags设置方法

Wish Tags的设置方法: 1.Tag是给Wish抓取你的产品信息用的,用户很少用Tag来搜索自己想要的商品.所以,tag要准确,不要一件衣服又说 Long sleeves又说Short sleeves.这样Wish就不好匹配,从而产品权重下降. 2.Tag的顺序一般来说是一级分类.二级分类.三级分类这样.用淘宝做测试,可以看到输入连衣裙 短袖 女装和输入女装 短袖 连衣裙,前出现的商品会一样,(付费用户在哪都享有特权)但是鼠标往下拉一点点就开始不一样了,而且两边衣服重复度也较低. 由于大部

Linux自动登陆的设置方法

前些天为了实现Linux自动登陆的方法,在网上查了很多资料,发现有不少方法,但网上有些方法的讲解不是特别清楚,或者已经过时.因此,特意整理了一下Linux自动登陆的设置方法.本文的测试环境为Centos 5.5. 1.设置GDMGDM是GNOME显示管理器,通过设置其配置文件/etc/gdm/custom.conf可以设置帐号自动登陆.设置方法如下:在/etc/gdm/custom.conf文件中添加以下内容[daemon]AutomaticLogin=usernameAutomaticLogi