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.結言
以上如果有什麼不正確的地方,望衆博友一起討論,一起進步。
終於開始使用手冊進行參考了,嘻嘻,當然剛開始還是有點不習慣的,但是查函數原型真的比百度強太多了,還有描述,真的毫不廢話,都是很精煉的。