在之前的文章中,我们大致说明了coredump的生成机制,也就是coredump文件的生成流程。
但是实际上,这个流程并不是coredump独用,而是一套通用流程。
在这个流程中,有信号产生方、信号存储方、信号消费方。
在这三个阶段,其中信号和中断有类似的地方,但是二者并不等价。
信号本质上是在软件层次上对中断机制的一种模拟,其主要有以下几种来源:
程序错误:除零,非法内存访问等。 外部信号:终端 Ctrl-C 产生 SGINT 信号,定时器到期产生SIGALRM等 显式请求:kill函数允许进程发送任何信号给其他进程或进程组。


信号如何被接收的在今天这篇文章并不做介绍,只对信号存储和消费两部分进行说明。

首先每个进程的结构体里都有信号的信息存储:
struct task_struct {
...
int sigpending;
...
struct signal_struct *sig;
sigset_t blocked;
struct sigpending pending;
...
}
sigpending 表示进程是否有信号需要处理(1表示有,0表示没有);成员 blocked 表示被屏蔽的信息,每个位代表一个被屏蔽的信号;成员 sig 表示信号相应的处理方法,其类型是 struct signal_struct。
在进程从用户态陷入内核态时,内核态完成了相关工作之后,返回用户态之前,都会例行对进程的信号队列进行检查。
这段逻辑是汇编实现的,因为在linux内核中,用户态的切换就是汇编来控制的。【可能有同学对用户态和内核态的切换不太了解,其实用大白话讲就是,只是对cpu的寄存器的赋值进行更换,跟普通的进程切换可能没什么区别,但是同时又有区别,因为用户态和内核态的堆栈是分离开的,这样二者在切换的时候是需要在两个堆栈上进行操作,并且保存上下文信息】


ENTRY(ret_from_sys_call)
...
ret_with_reschedule:
...
cmpl $0, sigpending(%ebx) // 检查进程的sigpending成员是否等于1
jne signal_return // 如果是就跳转到 signal_return 处执行
restore_all:
RESTORE_ALL
ALIGN
signal_return:
sti // 开启硬件中断
testl $(VM_MASK),EFLAGS(%esp)
movl %esp,%eax
jne v86_signal_return
xorl %edx,%edx
call SYMBOL_NAME(do_signal) // 调用do_signal()函数进行处理
jmp restore_all
可以看到在内核代码中,指定了哪些信号可以产生dump core文件
后续就是对linux的信号处理机制方面进行深究和学习。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




