人都会犯错,所以在编写程序时难免会出现 BUG。
有些 BUG 是业务逻辑上的错误导致的,一般不会导致程序崩溃,例如:原本要将两个数相加,但不小心把这两个数相减,而导致结果出错。这时我们可以通过在程序中,使用 printf
这类输出函数来进行打点调试。
但有些 BUG 是由于某些致命的操作而导致的,一般会导致程序崩溃,例如:访问未经申请的内存地址。由于程序会异常退出,所以一般不能通过 printf
这类输出函数进行打点调试。
另外,对于必现的 BUG (就是不管什么条件都会发生),一般可以通过 GDB 设置断点进行调试。但对于偶现的 BUG,由于在某些特定的条件下才会发生,所以比较难直接通过 GDB 进行调试。
那么,这时可以通过 Linux 提供的 coredump
文件进行调试。
在程序发生某些错误而导致进程异常退出时,Linux 内核会根据进程当时的内存信息,生成一个 coredump
文件。而 GDB 可以通过这个 coredump
文件重现当时导致进程异常退出的场景,并且可以通过 GDB 来找到导致进程异常退出的原因。
当进程接收到某些 信号
而导致异常退出时,就会生成 coredump
文件。那么,哪些信号会导致生成 coredump
文件呢?
会导致生成 coredump
文件的信号,如下表所示:
Signal | Action | Comment |
---|---|---|
SIGQUIT | Core | Quit from keyboard |
SIGILL | Core | Illegal Instruction |
SIGABRT | Core | Abort signal from abort |
SIGSEGV | Core | Invalid memory reference |
SIGTRAP | Core | Trace/breakpoint trap |
下面我们通过一个例子来说明怎么生成 coredump
文件。
从上面的表格可知,当进程接收到 SIGSEGV
信号时会生成 coredump
文件。SIGSEGV
信号是当进程访问错误(未经申请)内存地址时触发的,所以下面我们编写一个访问错误内存地址的程序:
int main(int argc, char *argv[])
{
char *addr = (char *)0; // 设置 addr 变量为内存地址 "0"
*addr = '\0'; // 向内存地址 "0" 写入数据
return 0;
}
在上面的例子中,由于内存地址 ”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
文件。
当进程从 内核态
返回到 用户态
前,内核会查看进程的信号队列中是否有信号没有处理,如果有就调用 do_signal
内核函数处理信号。我们可以通过下图来展示内核是怎么生成 coredump
文件的:
进程从内核态返回到用户态的地方有很多,如 从系统调用返回
、从硬中断处理程序返回
和 从进程调度程序返回
等。上图主要通过 从进程调度程序返回
作为示例,来展示内核是怎么生成 coredump
文件的。
下面我们来分析一下 coredump
文件生成过程的步骤:
当进程从内核态返回到用户态前,内核会查看进程的信号队列中是否有信号没有被处理,如果有就调用 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
文件。如果要处理的信号会触发生成 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
功能而导致的事故,故事如下:
我们上线了一个有 BUG 的 WEB 服务,这个程序是以
master-worker
模式运行的。master
进程的主要工作是监控worker
进程的运行情况,如果worker
进程挂掉,master
进程会创建新的worker
进程来继续工作。由于
worker
进程的代码存在漏洞,会导致worker
进程访问非法的内存地址而产生SIGSEGV
信号(段错误),而SIGSEGV
信号会触发生成coredump
文件。由于每次
worker
进程异常退出后,master
进程都会创建新的worker
进程来补充,所以最终导致worker
进程不断的异常退出和被创建。这样就不断的生成coredump
文件,最终导致磁盘被打满。
所以,经过上面的事故,我建议大家不要在生成环境打开 coredump
功能。那么,如果程序有问题怎么排查呢?
我的建议是摘掉线上的某一台机器,打开 coredump
功能,然后模拟发生异常的情况来进行排查。如果人工比较难模拟,那么可以通过使用 tcpcopy
这些工具来把线上的流量导入到调试机器进行调试。生成 coredump
文件后,可以使用 GDB
来进行调试。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/yHHYjxZjF7nc7urbilGzSA
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。