在linux中,Core是記憶體的意思。當程式運作過程中偵測到異常程式異常退出時, 系統把程式目前的記憶體狀況儲存在一個core檔中, 叫core dumped,也就資訊轉儲;作業系統偵測到目前行程異常時將透過訊號的方式通知目標進程對應的錯誤訊息,常見的訊號有SIGSEGV、SIGBUS等,預設進程接收到對應的訊號都有對應的處理機制。
本教學操作環境:linux7.3系統、Dell G3電腦。
在Linux下開發中,我們常聽到程式設計師說我的程式core掉了,通常出現這類的問題是低階bug中的記憶體存取越界、使用空指標、堆疊溢位等情況。使程式運作過程中異常退出或終止,滿足這些條件就會產生core的檔案。
為什麼會發生Coredump
Core就是記憶體的意思,這個字源自於很早以前製造記憶體的材料,一直延用到現在,當程式運作過程中偵測到異常程式異常退出時, 系統把程式目前的記憶體狀況儲存在一個core檔中, 叫core dumped,也就訊息轉儲,作業系統偵測到目前進程異常時會透過訊號的方式通知目標進程對應的錯誤訊息,常見的訊號有SIGSEGV,SIGBUS等,預設行程接收到對應的訊號都有對應的處理機制。
以Linux為例,Action則對應訊號的處理方式,紅色框標註為常見訊號
在此之前最好先了解下一個行程的記憶體佈局, Unix與Linux系統的行程空間佈局會稍微有點不同,核心空間會比Linux小,特別是核心與使用者行程採用分離的位址空間模式,這裡以Linux為例:
#coredump檔案的儲存位置
#我們知道在Linux系統中,如果進程崩潰了,系統核心會捕捉到進程崩潰訊息,然後將進程的coredump 資訊寫入到檔案中,這個檔案名稱預設是core 。儲存位置與對應的執行程式在同一目錄下,檔案名稱是core,大家可以透過下面的指令看到core檔案的存在位置:
Core_pattern的格式:
%u (數位)轉儲程序的實際UID
%G (數位)轉儲過程的實際GID
%s 引起轉儲的信號數
%t 轉儲時間,表示為自1970年1月1日00:00:00 0000(UTC)以來的秒數
% H 主機名(與uname(2)回傳的節點名相同)
%e 可執行檔名(無路徑前綴)
%E 可執行檔的路徑名,以斜線('/')替換為感嘆號('!')。
%C 崩潰過程的核心檔案大小軟資源限制(自Linux 2.6.24開始)
#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]; /* 属性的当前工作目录崩溃的过程*/ snprintf(cwd, PATH_MAX, "/proc/%s/cwd", argv[1]); chdir(cwd); /* 将输出写到该目录下的文件"core.info" */ fp = fopen("core.info", "w+"); if (fp == NULL) { exit(EXIT_FAILURE); } fprintf(fp, "argc=%d\n", argc); for (j = 0; j < argc; j++) { fprintf(fp, "argc[%d]=<%s>\n", j, argv[j]); } /* 计算标准输入(核心转储)中的字节数*/ tot = 0; while ((nread = read(STDIN_FILENO, buf, BUF_SIZE)) > 0) { tot += nread; } fprintf(fp, "Total bytes in core dump: %d\n", tot); return 0; }
注意一下: 这里是指在进程当前工作目录的下创建。通常与程序在相同的路径下。但如果程序中调用了chdir函数,则有可能改变了当前工作目录。这时core文件创建在chdir指定的路径下。有好多程序崩溃了,我们却找不到core文件放在什么位置。和chdir函数就有关系。当然程序崩溃了不一定都产生 core文件。
下面通过的命令可以更改coredump文件的存储位置,如下:
echo “|$PWD/core_pattern_pipe_test %p UID=%u GID=%g sig=%s” > /proc/sys/kernel/core_pattern
cat /proc/sys/kernel/core_pattern
查看路径已经变为如下:
下面带大家配置永久的core。只要出现内存访问越界、使用空指针、堆栈溢出等情况,都可以在这个目录下查看。
配置 core
1、首先在根目录下建立一个储存coredump文件的文件夹,命令如下:
mkdir /corefile
2、设置产生coredump文件的大小,命令如下:
ulimit -c unlimited
3、 执行以下两条命令:
echo “1” > /proc/sys/kernel/core_uses_pid //将1写入到该文件里 echo “/corefile/core-%e-%p-%t” > /proc/sys/kernel/core_pattern
将coredump产生的格式制定好写入core_pattern文件,这样当coredump产生时会直接以这种格式存入到根目录下的文件夹corefile中。
4、修改配置文件/etc/profile
vim /etc/profile
添加 ulimit -S -c unlimited > /dev/null 2>&1
执行命令生效该文件
5、 在配置文件/etc/rc.local中最后面添加信息(机器重启时会自动加载该命令):添加命令:
rm -rf /corefile/*
机器重启时清空该文件夹,由于产生的coredump文件很大,若不清空的话时间长了会将硬盘占满;
再执行以下两条命令:
echo “1” > /proc/sys/kernel/core_uses_pid echo “/corefile/core-%e-%p-%t” > /proc/sys/kernel/core_pattern
测试
下面写个例子测试一下是否配置好了corefile文件
#include
编译运行,注意这里需要-g选项编译。
进入前面创建的corefile文件夹:
出现core文件表示完成coredump配置。可以用通过readelf命令进行判断是否是core文件:
執行gdb閱讀core文件,指令為“gdb 程式 對應coredump文件”,這時就進入gdb的提示符號“(gdb)”。
從紅色方框截圖可以看到,程式中止是因為訊號11。
下面可以透過bt(backtrace)指令(或where)可以看到函數的呼叫堆疊情況:
即程式執行到test.cpp的第6行是出現段錯誤。原因是指向了空指標。
總結
造成程式coredump的原因有很多,這裡總結一下,主要是記憶體存取越界、使用執行緒不安全的函數、使用空指標、堆疊溢位等等。
這裡要說一下,gdb調試coredump,大部分時候還是只能從core檔案找出core的直覺原因,但是更根本的原因一般還是需要結合程式碼一起分析當時進程的運行上下文場景,才能推測出程式碼問題所在。
相關推薦:《Linux影片教學》
以上是linux core是什麼意思的詳細內容。更多資訊請關注PHP中文網其他相關文章!