1. Linux内核里面生成的core file文件相关的代码
2. core dump file 相关的设置
3. 如何在程序中调用代码生成 core dump file,程序又不用退出。
4. 使用gdb分析 core dump file 文件
5. 用gdb 生成core文件
1. Linux内核里面生成的core file文件相关的代码
------------------------------------------------------------------
get_signal_to_deliver 这里没判断是不是信号是不是要触发core dump,然后调用
最后会调用elf_core_dump
里面有一段这样变量vma的循环,应该是保存所有内存的? 不过应该还有其他信息的
1980 /* Write program headers for segments dump */ 1981 for (vma = first_vma(current, gate_vma); vma != NULL; 1982 vma = next_vma(vma, gate_vma)) { 1983 struct elf_phdr phdr; 1984 1985 phdr.p_type = PT_LOAD; 1986 phdr.p_offset = offset; 1987 phdr.p_vaddr = vma->vm_start; 1988 phdr.p_paddr = 0; 1989 phdr.p_filesz = vma_dump_size(vma, cprm->mm_flags); 1990 phdr.p_memsz = vma->vm_end - vma->vm_start; 1991 offset += phdr.p_filesz; 1992 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; 1993 if (vma->vm_flags & VM_WRITE) 1994 phdr.p_flags |= PF_W; 1995 if (vma->vm_flags & VM_EXEC) 1996 phdr.p_flags |= PF_X; 1997 phdr.p_align = ELF_EXEC_PAGESIZE; 1998 1999 size += sizeof(phdr); 2000 if (size > cprm->limit
2001 || !dump_write(cprm->file, &phdr, sizeof(phdr))) 2002 goto end_coredump; 2003 }
core dump file 相关的设置:
---------------------------------------
默认 linux 是没有dump core文件的,需要设置一下
widebright@:~/桌面$ ulimit -a
core file size (blocks, -c) 0 >>>>>>>>>>>>>>>>>这个设为0了,不会有core dump了
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
ulimit -c 1000 最大允许core文件有1000块 ?
ulimit -c unlimited 不做限制
另有/proc/sys/kernel/core_pattern core_pipe_limit core_uses_pid 等文件可以控制core 文件的名字,具体可以看上面说的函数的实现。
或者在内核里面查找core_pattern变量。
----------------------------------------------
如何为自己的进程产生core 文件,又不想退出这个进程?
系统只在程序崩溃退出时自动产生core file。 有的人像自己处理异常信号,然后自己产生一个core file,然后继续运行。那该怎么办呢? 如果自己在想产生core file的时候,调用abort 函数来生成文件,core文件是生成了,但自己的进程也退出了。为了进程退出,在网上找到两个办法:
=============================================
方法一: 先fork创建一个子进程,子进程拥有和父进程一样的
内存空间了,然后在子进程触发abort信号,让子进程进行core
dump。 这个fork看来还比较有意思的,子进程拥有父进程的一样
的内存空间,上次才看到有人想定时存档备份进程数据时,也是想fork一个
子进程出来,说是这样父进程在备份时也不用同步等待了。子进程可以
访问父进程的内容吧。
=============================================
方法来自
http://stackoverflow.com/questions/131439/how-can-a-c-program-produce-a-core-dump-of-itself-without-terminating
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <sys/time.h>
#include <time.h>
#include <sys/types.h>
#include <unistd.h>
#define mcrosec 1000000
void create_dump(void)
{
int * invalid = NULL;
if(!fork()) {
// Crash the app in your favorite way here
abort(); //和 kill(getpid(), SIGABRT);应该一样的
*invalid = 42; //应该不会到这里来了吧。
}
}
int main(int argc,char **argv)
{
int i =0;
while(1){
usleep( 2*mcrosec);
i++;
printf("ddd\n");
if( i==5)
create_dump();
}
return 0;
}
-------------------------------------------------------
使用gdb分析一下这个core文件哈
widebright@:~/桌面$ gdb -core core
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
[New Thread 3320]
Core was generated by `./a.out'.
Program terminated with signal 6, Aborted.
#0 0x00982416 in __kernel_vsyscall ()
(gdb) file ./a.out
Reading symbols from /home/widebright/桌面/a.out...done.
(gdb) bt ///查出错时候的堆栈
#0 0x00982416 in __kernel_vsyscall ()
#1 0x00ec6e71 in ?? ()
#2 0x00ff8ff4 in ?? ()
#3 0x00eca34e in ?? ()
#4 0x00000006 in ?? ()
#5 0xbfa5fd80 in ?? ()
#6 0x0804845f in create_dump () at main.c:18
#7 0x0804849c in main (argc=1, argv=0xbfa5ff04) at main.c:31
(gdb) frame 7 //切换的调用main的调用堆栈环境上去
#7 0x0804849c in main (argc=1, argv=0xbfa5ff04) at main.c:31
31 create_dump();
(gdb) print i //i 等于5的时候调用的dump 呵呵
$1 = 5
=========================================
方法二:调用gcore命令为指定的进程生成core 文件
=========================================
http://forums.freebsd.org/archive/index.php/t-8268.html
char cmd[50];
sprintf(cmd, "gcore %u", getpid());
system(cmd);
-----------------------------------
widebright@:~/桌面$ ps -ef |grep a.out
1000 3665 3546 0 10:53 pts/0 00:00:00 ./a.out
1000 3669 3665 0 10:53 pts/0 00:00:00 [a.out] <defunct>
1000 3686 2937 0 10:53 pts/2 00:00:00 grep --color=auto a.out
widebright@:~/桌面$ sudo gcore 3665
[sudo] password for widebright:
0x00c5b416 in __kernel_vsyscall ()
Saved corefile core.3665
---------------------------
widebright@:~/桌面$ gdb -core core.3665
GNU gdb (Ubuntu/Linaro 7.2-1ubuntu11) 7.2
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i686-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
[New Thread 3665]
Core was generated by `/home/widebright/桌面/a.out'.
#0 0x00c5b416 in __kernel_vsyscall ()
(gdb) file a.out
Reading symbols from /home/widebright/桌面/a.out...done.
(gdb) bt
#0 0x00c5b416 in __kernel_vsyscall ()
#1 0x00d2afc0 in ?? ()
#2 0x00d5c1ac in ?? ()
#3 0xbfed8b90 in ?? ()
#4 0x08048481 in main (argc=1, argv=0xbfed8c74) at main.c:27
(gdb) p i
No symbol "i" in current context.
(gdb) frame 4
#4 0x08048481 in main (argc=1, argv=0xbfed8c74) at main.c:27
27 usleep( 2*mcrosec);
(gdb) p i
$1 = 48
=============================
在我机器上gcore命令就个shell脚本,自动生成一个gdb的脚本,attach 指定的进程,然后调用gcore这个gdb 命令生成core文件,然后detach让进程继续进行。
(gdb) help generate-core-file
Save a core file with the current state of the debugged process.
Argument is optional filename. Default filename is 'core.<process_id>'.
(gdb) help gcore
Save a core file with the current state of the debugged process.
Argument is optional filename. Default filename is 'core.<process_id>'.
widebright@:~/桌面$ file /usr/bin/gcore
/usr/bin/gcore: POSIX shell script text executable
=============================
cat /usr/bin/gcore
#!/bin/sh
# Copyright (C) 2003, 2005, 2007, 2008, 2009, 2010
# Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# gcore.sh
# Script to generate a core file of a running program.
# It starts up gdb, attaches to the given PID and invokes the gcore command.
#
if [ "$#" -eq "0" ]
then
echo "usage: gcore [-o filename] pid"
exit 2
fi
# Need to check for -o option, but set default basename to "core".
name=core
if [ "$1" = "-o" ]
then
if [ "$#" -lt "3" ]
then
# Not enough arguments.
echo "usage: gcore [-o filename] pid"
exit 2
fi
name=$2
# Shift over to start of pid list
shift; shift
fi
# Create a temporary file. Use mktemp if available, but cope if it is not.
tmpfile=`mktemp ${name}.XXXXXX 2>/dev/null` || {
tmpfile=${name}.$$
if test -e $tmpfile; then
echo "Could not create temporary file $tmpfile"
exit 1
fi
touch $tmpfile
}
trap "rm -f $tmpfile" EXIT
# Initialise return code.
rc=0
# Loop through pids
for pid in $*
do
# Write gdb script for pid $pid.
cat >>$tmpfile <<EOF
attach $pid
gcore $name.$pid
detach
quit
EOF
gdb -x $tmpfile -batch
if [ -r $name.$pid ] ; then
rc=0
else
echo gcore: failed to create $name.$pid
rc=1
break
fi
done
exit $rc