core文件描述
参考:man手册
1.什么是core dump
许多程序和操作系统崩溃或者出错时,一般会自动生成一个叫core 的文件(二进制文件)。因为某些信号的默认动作是导致进程终止并产生一个core dump文件(signal(7)),core文件记录的是程序崩溃时的内存映像,包含寄存器的状态,堆栈指针,内存管理信息还有各种函数调用堆栈信息等,并且加入了调试信息(例如,gdb(1)),core文件生成的过程叫core dump
通过工具分析这个文件(如 GNU Binutils Binary File Descriptor library (BFD),GNU Debugger (gdb),mdb等),我们可以定位到程序异常退出时对应的堆栈
调用等各种状态信息,并找出问题所在并及时进行解决。
2.core一般性原因(其实就是一些常见的调试错误)
1.内存访问越界
a)下表使用错误,导致数组访问越界
b)搜索字符窜时,没有正确使用结束符
c)没有使用安全的读写复制函数
2.多线程程序使用了线程不安全的函数(博主对线程不安全函知之甚少,就偷懒了)
应该使用下面这些可冲入的函数,他们很容易被用错:
asctime_r(3c) gethostbyname_r(3n) getservbyname_r(3n)ctermid_r(3s) gethostent_r(3n) getservbyport_r(3n) ctime_r(3c)getlogin_r(3c)getservent_r(3n) fgetgrent_r(3c) getnetbyaddr_r(3n) getspent_r(3c)fgetpwent_r(3c) getnetbyname_r(3n) getspnam_r(3c) fgetspent_r(3c)getnetent_r(3n) gmtime_r(3c) gamma_r(3m) getnetgrent_r(3n) lgamma_r(3m) getauclassent_r(3)getprotobyname_r(3n) localtime_r(3c) getauclassnam_r(3) etprotobynumber_r(3n)nis_sperror_r(3n) getauevent_r(3) getprotoent_r(3n) rand_r(3c) getauevnam_r(3)getpwent_r(3c) readdir_r(3c) getauevnum_r(3) getpwnam_r(3c) strtok_r(3c) getgrent_r(3c)getpwuid_r(3c) tmpnam_r(3s) getgrgid_r(3c) getrpcbyname_r(3n) ttyname_r(3c)getgrnam_r(3c) getrpcbynumber_r(3n) gethostbyaddr_r(3n) getrpcent_r(3n)
3.多线程读写的数据未加锁进行保护
4.非法指针
a)空指针
b)将某种非指针类型或结构的内存转换成指针来使用
5.堆栈溢出
3.core文件的存储位置以及设置生成core文件
1.core文件默认的存储位置与对应的可执行程序在同一目录,文件名是core.(注:但是可以通过chdir()函数指定core文件创建的路径)
cat /proc/sys/kernel/core_pattern
cat /proc/sys/kernel/core_pattern
2.设置生成core文件
ulimit -c //查看core-dump的状态,若返回0。则表示不会产生对应的core-dump
ulimit -c[size] //指定对应的字符大小,例如:ulimit -c 1024,数字最好大于3
ulimit -c unlimited //表示产生的core-dump大小不受限制(加入文件 /etc/profile)
3.gdb利用core文件进行调试
gdb[exec file] [core file] //查看core文件的内容
bt //用来进入gdb后,来定位core-dump的文件->行
4.不产生core文件的几种情况
*进程没有写入core dump文件的权限。(默认情况下,core file称为core,并在当前工作目录中创建。)如果core文件它的目录被创建,并且是nonwritable的,core文件就会创建失败,或者如果一个具有相同名称的文件已存在,不可写或是不正规的文件(例如,它是一个目录或符号链接)都会失败。
*将用于core dump,但是相同的文件名称已经存在,并且有多个硬链接文件。
*文件系统的core dump被创建为已满;或已用完默认的字节数;或是设为只读;或用户已达到文件系统的配额数量等。
*要创建core dump的目录不存在。
* RLIMIT_CORE(core文件大小)或 RLIMIT_FSIZE(文件大小)的进程的资源限制设置为零;看getrlimit(2)与查看shell文件的ulimit下显示的文件((limit in csh(1))。
*进程所执行的二进制文件没有启用读权限。
*进程正在执行由用户(组)所拥有的set-user-ID (set-group-ID)程序,而不是该进程的真实用户(组)ID。(不过,可以查看 prctl(2) PR_SET_DUMPABLE的操作,和文件过程描述在 /proc/sys/fs/suid_dumpable file in proc(5)中.)
*(自从Linux 3.7内核配置)没有CONFIG_COREDUMP选项。
此外,一个core dump文件可以排除该进程的地址空间的一部分,如果 madvise(2) MADV_DONTDUMP标志存在的
5.core_pattern的格式(/proc/sys/kernel/core_pattern)
可以在core_pattern模板下使用的变量还有:
%%单个%字符
%p被dump的进程的进程ID
%u(数字)被dump的进程的实际用户ID
% g(数字)被dump的进程的实际组ID
%s导致本次dump的信号
%t dump的时间,秒表示由于时代,1970-01-0 00:00:00 + 0000(UTC)
% h主机名(same as nodename returned by uname(2)))
%e可执行文件名(无路径前缀)
%E生成可执行的路径,以斜杠(/)取代标记('!')。
%C core文件资源大小限制崩溃的进程(自Linux 2.6.24)
6.编写一个利用管道指定core_pattern_pipe_test(在文件 /proc/)
$ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
$ su
Password:
# echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
/proc/sys/kernel/core_pattern
# exit
$ sleep 100
^\ # type control-backslash
Quit (core dumped)
$ cat core.info
argc=5
argc[0]=</home/mtk/core_pattern_pipe_test>
argc[1]=<20575>
argc[2]=<UID=1000>
argc[3]=<GID=100>
argc[4]=<sig=3>
Total bytes in core dump: 282624
$ cc -o core_pattern_pipe_test core_pattern_pipe_test.c
$ su
Password:
# echo "|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s" > \
/proc/sys/kernel/core_pattern
# exit
$ sleep 100
^\ # type control-backslash
Quit (core dumped)
$ cat core.info
argc=5
argc[0]=</home/mtk/core_pattern_pipe_test>
argc[1]=<20575>
argc[2]=<UID=1000>
argc[3]=<GID=100>
argc[4]=<sig=3>
Total bytes in core dump: 282624
Program source
/* core_pattern_pipe_test.c */
#define _GNU_SOURCE
#include <sys/stat.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUF_SIZE 1024
int main(int argc, char *argv[])
{
int tot, j;
ssize_t nread;
char buf[BUF_SIZE];
FILE *fp;
char cwd[PATH_MAX];
/* Change our current working directory to that of the
crashing process */
snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]);
chdir(cwd);
/* Write output to file "core.info" in that directory */
fp = fopen("core.info", "w+");
if (fp == NULL)
exit(EXIT_FAILURE);
/* Display command-line arguments given to core_pattern
pipe program */
fprintf(fp, "argc=%d\n", argc);
for (j = 0; j < argc; j++)
fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
/* Count bytes in standard input (the core dump) */
tot = 0;
while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
tot += nread;
fprintf(fp, "Total bytes in core dump: %d\n", tot);
exit(EXIT_SUCCESS);
}
fprintf(fp, "argc=%d\n", argc);
for (j = 0; j < argc; j++)
fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]);
/* Count bytes in standard input (the core dump) */
tot = 0;
while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0)
tot += nread;
fprintf(fp, "Total bytes in core dump: %d\n", tot);
exit(EXIT_SUCCESS);
}
7.结言
以上如果有什么不正确的地方,望众博友一起讨论,一起进步。
终于开始使用手册进行参考了,嘻嘻,当然刚开始还是有点不习惯的,但是查函数原型真的比百度强太多了,还有描述,真的毫不废话,都是很精炼的。