首页 » 网站推广 » php生成coredump技巧_一文读懂 coredump文件是若何生成的

php生成coredump技巧_一文读懂 coredump文件是若何生成的

访客 2024-11-24 0

扫一扫用手机浏览

文章目录 [+]

有些 BUG 是业务逻辑上的缺点导致的,一样平常不会导致程序崩溃,例如:原来要将两个数相加,但欠妥心把这两个数相减,而导致结果出错。
这时我们可以通过在程序中,利用 printf 这类输出函数来进行打点调试。

但有些 BUG 是由于某些致命的操作而导致的,一样平常会导致程序崩溃,例如:访问未经申请的内存地址。
由于程序会非常退出,以是一样平常不能通过 printf 这类输出函数进行打点调试。

php生成coredump技巧_一文读懂  coredump文件是若何生成的

其余,对付必现的 BUG (便是不管什么条件都会发生),一样平常可以通过 GDB 设置断点进行调试。
但对付偶现的 BUG,由于在某些特定的条件下才会发生,以是比较难直接通过 GDB 进行调试。

php生成coredump技巧_一文读懂  coredump文件是若何生成的
(图片来自网络侵删)

那么,这时可以通过 Linux 供应的 coredump 文件进行调试。

一、coredump 文件天生过程

在程序发生某些缺点而导致进程非常退出时,Linux 内核会根据进程当时的内存信息,天生一个 coredump 文件。
而 GDB 可以通过这个 coredump 文件重现当时导致进程非常退出的场景,并且可以通过 GDB 来找到导致进程非常退出的缘故原由。

当进程吸收到某些 旗子暗记 而导致非常退出时,就会天生 coredump 文件。
那么,哪些旗子暗记会导致天生 coredump 文件呢?

会导致天生 coredump 文件的旗子暗记,如下表所示:

SignalActionCommentSIGQUITCoreQuit from keyboardSIGILLCoreIllegal InstructionSIGABRTCoreAbort signal from abortSIGSEGVCoreInvalid memory referenceSIGTRAPCoreTrace/breakpoint trap

下面我们通过一个例子来解释怎么天生 coredump 文件。

从上面的表格可知,当进程吸收到 SIGSEGV 旗子暗记时会天生 coredump 文件。
SIGSEGV 旗子暗记是当进程访问缺点(未经申请)内存地址时触发的,以是下面我们编写一个访问缺点内存地址的程序:

int main(int argc, char argv[]){ char addr = (char )0; // 设置 addr 变量为内存地址 "0" addr = '\0'; // 向内存地址 "0" 写入数据 return 0;}

【嵌入式物联网单片机学习】嵌入式物联网开拓须要学的东西比较多,大家可以加下面微信一起学习,整理了100多G(全网最全)的学习资料包(持续更新)、最新的学习路线思维导图。

各种学习群、项目开拓教程。
还可以围不雅观我朋友圈中的一手行业,每周的技能大咖直播答疑吹水。

点击这里加我嵌入式物联网单片机学习

在上面的例子中,由于内存地址 ”0“ 并没有通过调用 malloc 函数申请,以是当向地址 ”0“ 写入数据时将会导致 段缺点,进程将会吸收到 SIGSEGV 旗子暗记。

当进程吸收到 SIGSEGV 旗子暗记后,内核将会根据进程当时的内存信息天生 coredump 文件,并且把进程杀去世。

我们将上面的程序编译并且运行后,会创造程序非常退出,并且天生一个名为 core.xxx 的文件,这个文件便是 coredump 文件。
如下图所示:

把稳:

编译的时候记得加上 -g 参数表示保留调试信息,否则利用 GDB 调试时会找不到函数名或者变量名。

如果没有天生 coredump 文件的话,一样平常是受到资源限定,先利用命令 ulimit -c unlimited 设置资源不受限定。

coredump 文件点后面的数字是进程的 PID。

现在我们只须要输入如下命令,即可利用 GDB 合营 coredump 文件来调试程序了:

$ gdb ./coredump ./core.6359

GDB 运行后会停滞在发生非常的代码处,并且将发生非常的代码打印出来,如下图:

从上面的输出可以看到,GDB 除了会将发生非常的代码打印到终端外,还会将其所在的函数、文件名和所在文件的行数也打印出来,这样我们就很快能定位到哪行代码导致非常的。

二、coredump文件天生事理

前面先容过,当进程吸收到某些 旗子暗记 而导致非常退出时,就会天生 coredump 文件。

当进程从 内核态 返回到 用户态 前,内核会查看进程的旗子暗记行列步队中是否有旗子暗记没有处理,如果有就调用 do_signal 内核函数处理旗子暗记。
我们可以通过下图来展示内核是怎么天生 coredump 文件的:

进程从内核态返回到用户态的地方有很多,如 从系统调用返回、从硬中断处理程序返回 和 从进程调度程序返回 等。
上图紧张通过 从进程调度程序返回 作为示例,来展示内核是怎么天生 coredump 文件的。

下面我们来剖析一下 coredump 文件天生过程的步骤:

1. 旗子暗记处理 do_signal()

当进程从内核态返回到用户态前,内核会查看进程的旗子暗记行列步队中是否有旗子暗记没有被处理,如果有就调用 do_signal 内核函数处理旗子暗记。
我们来看看 do_signal 函数的实现:

static void fastcall do_signal(struct pt_regs regs){ siginfo_t info; int signr; struct k_sigaction ka; sigset_t oldset; ... signr = get_signal_to_deliver(&info, &ka, regs, NULL); ...}

上面代码去掉了很多与天生 coredump 文件无关的逻辑,终极我们可以看到,do_signal 函数紧张调用 get_signal_to_deliver 内核函数来进行进一步的处理。

get_signal_to_deliver 内核函数的紧张事情是从进程的旗子暗记行列步队中获取一个旗子暗记,然后根据旗子暗记的类型来进行不同的操作。
我们紧张关注天生 coredump 文件干系的逻辑,如下代码:

int get_signal_to_deliver(siginfo_t info, struct k_sigaction return_ka, struct pt_regs regs, void cookie){ sigset_t mask = ¤t->blocked; int signr = 0; ... for (;;) { ... // 1. 从进程旗子暗记行列步队中获取一个旗子暗记 signr = dequeue_signal(current, mask, info); ... // 2. 判断是否会天生 coredump 文件的旗子暗记 if (sig_kernel_coredump(signr)) { // 3. 调用 do_coredump() 函数天生 coredump 文件 do_coredump((long)signr, signr, regs); } ... } ...}

上面代码去掉了与天生 coredump 文件无关的逻辑,末了我们可以看到 get_signal_to_deliver 函数紧张完成三个事情:

调用 dequeue_signal 函数从进程的旗子暗记行列步队中获取一个旗子暗记。
调用 sig_kernel_coredump 函数判断旗子暗记是否会天生 coredump 文件。
如果旗子暗记会天生 coredump 文件,那么就调用 do_coredump 函数天生 coredump 文件。
2. 天生 coredump 文件

如果要处理的旗子暗记会触发生成 coredump 文件,那么内核就会调用 do_coredump 函数来天生 coredump 文件。
do_coredump 函数的实现如下:

int do_coredump(long signr, int exit_code, struct pt_regs regs){ char corename[CORENAME_MAX_SIZE + 1]; struct mm_struct mm = current->mm; struct linux_binfmt binfmt; struct inode inode; struct file file; int retval = 0; int fsuid = current->fsuid; int flag = 0; int ispipe = 0; binfmt = current->binfmt; // 当提高程所利用的可实行文件格式(如ELF格式) ... // 1. 判断当提高程可天生的 coredump 文件大小是否受到资源限定 if (current->signal->rlim[RLIMIT_CORE].rlim_cur < binfmt->min_coredump) goto fail_unlock; ... // 2. 天生 coredump 文件名 ispipe = format_corename(corename, core_pattern, signr); ... // 3. 创建 coredump 文件 file = filp_open(corename, O_CREAT|2|O_NOFOLLOW|O_LARGEFILE|flag, 0600); ... // 4. 把进程的内存信息写入到 coredump 文件中 retval = binfmt->core_dump(signr, regs, file);fail_unlock: ... return retval;}

经由代码精简后,终极可以看到 do_coredump 函数完成四个事情:

判断当提高程可天生的 coredump 文件大小是否受到资源限定。
如果不受限定,那么调用 format_corename 函数天生 coredump 文件的文件名。
接着调用 filp_open 函数创建 coredump 文件。
末了根据当提高程所利用的可实行文件格式来选择相应的添补方法来添补 coredump 文件的内容,对付 ELF文件格式 利用的是 elf_core_dump 方法。

elf_core_dump 方法的紧张事情是:把进程的内存信息和内容写入到 coredump 文件中,并且以 ELF文件格式 作为 coredump 文件的存储格式。
有兴趣的可以自行阅读 elf_core_dump 方法的代码,这里就不作进一步的讲授了。

三、生产环境该当打开 coredump 功能吗?

末了,我们来谈论一下在生产环境应不应该打开 coredump 功能。

笔者遇过在生产环境打开 coredump 功能而导致的事件,故事如下:

我们上线了一个有 BUG 的 WEB 做事,这个程序因此 master-worker 模式运行的。
master 进程的紧张事情是监控 worker 进程的运行情形,如果 worker 进程挂掉,master 进程会创建新的 worker 进程来连续事情。

由于 worker 进程的代码存在漏洞,会导致 worker 进程访问造孽的内存地址而产生 SIGSEGV 旗子暗记(段缺点),而 SIGSEGV 旗子暗记会触发生成 coredump 文件。

由于每次 worker 进程非常退出后,master 进程都会创建新的 worker 进程来补充,以是终极导致 worker 进程不断的非常退出和被创建。
这样就不断的天生 coredump 文件,终极导致磁盘被打满。

以是,经由上面的事件,我建议大家不要在天生环境打开 coredump 功能。
那么,如果程序有问题怎么排查呢?

我的建议是摘掉线上的某一台机器,打开 coredump 功能,然后仿照发生非常的情形来进行排查。
如果人工比较难仿照,那么可以通过利用 tcpcopy 这些工具来把线上的流量导入到调试机器进行调试。
天生 coredump 文件后,可以利用 GDB 来进行调试。

end

原文链接:https://mp.weixin.qq.com/s/zJyFaxsXa4GPsjXWyoXrqw

文章转载自:嵌入式与Linux那些事文章来源于:一文读懂 | coredump文件是如何天生的

原文链接:一文读懂 | coredump文件是如何天生的

相关文章

介绍直播新纪元,轻松进入直播的五大步骤

随着互联网技术的飞速发展,直播行业在我国逐渐崛起,越来越多的人选择通过直播这一新兴媒介展示自己、分享生活、传递价值。对于许多新手来...

网站推广 2025-01-03 阅读1 评论0

介绍相机美颜原理,科技与美学的完美结合

随着科技的发展,智能手机的摄像头功能日益强大,美颜相机成为了许多人拍照的首选。美颜相机不仅满足了人们对于美的追求,更在视觉上给人带...

网站推广 2025-01-03 阅读1 评论0

介绍磁铁的制造,科学与艺术的完美结合

磁铁,一种神秘的物质,自古以来就吸引了无数人的目光。它不仅具有独特的磁性,还能在工业、医疗、科研等领域发挥重要作用。磁铁是如何制造...

网站推广 2025-01-03 阅读1 评论0

介绍电瓶激活方法,让电池焕发新生

随着科技的不断发展,电动汽车逐渐成为人们出行的首选。而电瓶作为电动汽车的核心部件,其性能直接影响着车辆的续航里程和行驶体验。新购买...

网站推广 2025-01-03 阅读1 评论0