대개 응용의 crash가 날 경우, core파일을 통해 디버깅할 수 있는데, 

간혹 생성되지 않을 경우가 있다. 

 웬만한 것을 건들지 않는다는 가정하에 간단한 해결책은 

ulimit -a 로 core dump에 대한 size가 너무 적거나 0이 되어 있는지 확인하고 이를, 

ulimit -c unlimited로 해주는 것이 가장 속편하다. 


core는 프로그램의 비정상적인 종료(세그먼트 폴트 등)가 발생하는 경우
커널에서 해당 프로세스와 관련된 메모리를 덤프시킨 파일이다.

아래와 같이 리눅스는 기본적으로 코어덤프를 하지 않도록 되어있다.
# ulimit -aS 또는 ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
pending signals                 (-i) 1024
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 2048
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 2047
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited 


코어덤프를 하도록 설정하려면 위 부분에서
core file size          (blocks, -c) 0 이부분이 값(KB)나 unlimited로 되어있어야만 한다.

- core dump를 하도록 설정하는 방법
# ulimit -c unlimited
# ulimit -c 1048576 (KB) - 1G 제한을 두는 경우

- 간단하게 dump된 core 파일에서 문자열(string)만을 보려면
# strings core | more

- 자세한 debugging을 원할 경우에는 gdb라는 툴을 사용하면 된다.(gdb 맨페이지 참고)


예전에는 단순히 core가 dump될 때 단순히 core라는 이름으로 생성이 되었는데
이 경우 어떤 프로세스에서 core가 발생했는지 확인하는 문제가 있었다.
하지만 요 근래의 Red Hat Linux를 보면 core.PID로 생성이 된다.
core와 관련된 커널 파라미터 설정은 다음과 같다.

# sysctl -a | grep core
kernel.core_pattern = core
kernel.core_uses_pid = 1

# cat /proc/sys/kernel/core_pattern
core

# cat /proc/sys/kernel/core_uses_pid
1  (0일 경우 pid를 출력하지 않음)


- core 덤프가 발생할 때 프로세스 실행파일명으로 core 덤프를 떨어뜨리는 방법
1) sysctl -w kernel.core_pattern = core.%e  (reboot후 초기화 된다.)

2) echo "core.%e" > /proc/sys/kernel/core_pattern

3) /etc/sysctl.conf 파일에 아래 내용을 등록해 준다.
kernel.core_pattern = core.%e

- 강제로 특정 프로세스에 대한 core를 발생시키는 방법
디버깅을 위해 특정 프로세스에 대해 강제로 core dump를 발생시켜야 하는 경우
kill 커맨드를 이용할 수 있다.

# kill -l
 1) SIGHUP       2) SIGINT       3) SIGQUIT      4) SIGILL
 5) SIGTRAP      6) SIGABRT      7) SIGBUS       8) SIGFPE
 9) SIGKILL     10) SIGUSR1     11) SIGSEGV     12) SIGUSR2
13) SIGPIPE     14) SIGALRM     15) SIGTERM     17) SIGCHLD
18) SIGCONT     19) SIGSTOP     20) SIGTSTP     21) SIGTTIN
22) SIGTTOU     23) SIGURG      24) SIGXCPU     25) SIGXFSZ
26) SIGVTALRM   27) SIGPROF     28) SIGWINCH    29) SIGIO
30) SIGPWR      31) SIGSYS      34) SIGRTMIN    35) SIGRTMIN+1
36) SIGRTMIN+2  37) SIGRTMIN+3  38) SIGRTMIN+4  39) SIGRTMIN+5
40) SIGRTMIN+6  41) SIGRTMIN+7  42) SIGRTMIN+8  43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8  57) SIGRTMAX-7  58) SIGRTMAX-6  59) SIGRTMAX-5
60) SIGRTMAX-4  61) SIGRTMAX-3  62) SIGRTMAX-2  63) SIGRTMAX-1
64) SIGRTMAX

위의 시그널 중에서 8)SIGFPE 또는 3)SIGQUIT 를 통해 core를 dump시킬 수 있다.
# top (top 실행)
# ps -ef | grep -i top (top 프로세스 PID 확인, 다른 터미널에서)
root     31775 29667  0 14:30 pts/3    00:00:00 top

# kill -SIGFPE 31775

위와 같이 하면 top을 실행한 디렉토리에 core.top.31775가 생성되어있음을 확인할 수 있다.


- gcore를 이용한 core dump 발생
디버깅을 위해 현재 실행중인 프로세스를 강제로 core dump를 생성할 필요가 있는 경우 gcore를 이용할 수 있다.

# top (top 실행)
# ps -ef | grep -i top (top 프로세스 PID 확인, 다른 터미널에서)
root     31775 29667  0 14:30 pts/3    00:00:00 top

# gcore 31775
gcore: core.31775 dumped

참고 : gcore 바이너리는 gdb 패키지에 포함돼 있다. (gdb-6.3.0.0-1.143.el4.i386.rpm)


=========================================================================================================================================

[ 참고 자료]

아래는 각각의 OS 플랫폼에서 core 파일 정보를 확인하는 결과이다.
각각의 플랫폼에서는 다음과 같은 결과가 나왔다 :

$ uname -a;file core                                     
SunOS v880 5.8 Generic_117350-51 sun4u sparc SUNW,Sun-Fire-880
core:           ELF 32-bit MSB core file SPARC Version 1, from 'a.out'

$ uname -a; file core
AIX aix5 3 5 0001D01F4C00
core: AIX core file 32-bit, a.out

% uname -a; file core
HP-UX hp1123 B.11.23 U 9000/800 190494686 ??????-????? ???̼???
core:           core ???? - 'a.out' - SIGBUS ????

$ uname -a; file core.528 
Darwin castepo.local 9.3.0 Darwin Kernel Version 9.3.0: Fri May 23 00:49:16 PDT 2008; root:xnu-1228.5.18~1/RELEASE_I386 i386
core.528: Mach-O core i386
때때로 여러개의 프로세스를 마구 띄우는 daemon 을 작업하다 보면 뜬 프로세스들 중 하나가 죽을 경우에 생기는 core 파일이 도대체 어느 프로그램이 죽어서 생긴 것인지 알 수 없을 경우가 있다. 물론, 하나씩 디버거로 읽어서 뭔가 좀 말이 되는 콜스택을 보여준다든지 하는 녀석을 대충 지레짐작해서 얘이거니 하고 분석할 수도 있지만, 기분 나쁘다.

리눅스 맨페이지에 따르면 커널 버젼 2.6 이후, 그리고 2.4.21 이후의 커널에 다음의 기능이 추가되어 있다고 한다 :
$ man core | col -b 
.
.
.
   Naming of core dump files
       By default, a core dump file is    named  core,  but  the    /proc/sys/ker-
       nel/core_pattern file (since Linux 2.6 and 2.4.21) can be set to define
       a template that is used to name core dump files.  The template can con-
       tain  % specifiers which are substituted by the following values when a
       core file is created:

     %%  A single % character
     %p  PID of dumped process
     %u  real UID of dumped process
     %g  real GID of dumped process
     %s  number of signal causing dump
     %t  time of dump (seconds since 0:00h, 1 Jan 1970)
     %h  hostname (same as 'nodename' returned by uname(2))
     %e  executable filename


말인 즉슨, 다음과 같이 하면 core file 이 생성될 때 그 파일의 이름을 어떻게 지을 것인가 하는 문제를 사용자가 설정할 수 있다는 이야기인데, cut to the chase, 결론부터 말하면, 다음과 같이 하면 실행파일의 이름을 가지고 core 파일의 이름을 만들 수 있다 :

# cat > /proc/sys/kernel/core_pattern
core.%e
^D
# 
저와 같이 해 두고 아까 컴파일한 파일을 실행시켜 보면,
$ ./a.out 
hello
Segmentation fault (core dumped)
$ ls
a.c  a.out*  core.a.out
$

참고 및 인용사이트 : http://altibase.tistory.com/241

신고
Posted by 라판