生活角度的信号
a.信号在生活中,随时可以产生(信号的产生和我是异步的)
b.你能认识这个信号
c.我们知道信号产生了,我能识别这个信号,信号该怎么处理
d.我们可能正在做着更重要的事情,把到来的信号暂不处理(1.我记得这个事 2.合适的时候处理)
信号介绍
在bash上执行命令kill -l便可看到系统定义的所有信号

我们只研究前31个信号,后面31个是实时信号这里不做研究
每个信号都有一个编号和一个宏定义名称,这些宏定义都可以在signal.h中找到,在man手册中还可以找到各种信号的详细信息
man 7 signal
这里具体介绍了信号在什么时候产生,处理的动作是什么
信号概念的基本储备
信号:Linux系统提供的一种,向指定进程发送特定事件的方式,做识别和处理。
信号产生是异步的。
信号处理常见方式
1、忽略该信号
2、执行信号的默认处理动作(终止自己、暂停、忽略.....)
3、提供一个信号处理函数,要求内核在处理信号时切换到用户态执行这个处理函数,这种方式称为捕捉一个异常

Core和Term:默认动作都是终止,但Core能产生Core文件
如何理解信号的发送和保存?
进程---task_struct---struct---成员变量---用位图来保存收到的信号
uint32_t signals;
0000 0000 0000 0000 0000 0000 0000 0000
发送信号:修改指定进程pcb中的信号指定位图,0->1,写信号
pcb:内核数据结构对象,只有OS有资格修改内核结构对象中的值
信号产生具体过程
kill命令
通过kill命令向指定进程发送指定信号
kill -数字 进程号
通过终端按键来产生信号
ctrl+c 2)SIGINT 向当前进程发送2号信号
ctrl+\ 3)SIGQUIT向当前进程发送3号信号
SIGINT的默认处理动作是终止进程,SIGQUIT的默认处理动作是终止进程并Core Dump,我们在Linux环境下来验证一下,先来了解一下什么是Core Dump
当一个进程要异常终止时,可以选择把进程的用户空间内存数据全部保存在磁盘上,文件名通常是core,这叫做Core Dump。进程异常终止通常是因为有BUG,比如非法访问内存导致段错误,事后可以用调试器检查core文件以查清楚错误原因,这叫做事后调试,一个进程允许产生多大的core文件取决于进程的Resource Limit(这个信息保存在PCB中),默认是不允许改变这个限制,允许产生core文件。首先用ulimit命令来改变shell进程的Resource Limit,允许core文件最大为1024k

通过信号返回值我们发现有一个core dump位。
云服务器默认关闭这个core文件功能
ulimit -c 1024 //打开这个文件功能
写一个死循环程序

编译并执行程序:

看到的现象是先打印出pid然后一直在死循环,按下组合键ctrl+\后退出并提示core dumped
test程序也会core dump的原因是我们先修改了shell的Resource Limit值,而test进程是由shell产生的所以test进程的PCB也是由shell复制而来,所以test进程和shell就具有相同的Resource Limit值,所以就会产生core dump了。
如图所示就是产生的core文件
最新的Linux版本所生成的core文件没有后缀,同一个文件如果多次执行多次异常终止,那么生成的core文件还是一份。这样就避免了一份文件生成多份core文件占内存。
调用系统函数来向进程发信号
kill函数

参数解释:
第一个参数进程id
第二个参数信号标号
返回值:成功返回0失败返回-1
./mykill 2 1234
int main(int argc, char *argv[])
{
if(argc != 3)
{
std::cerr << "Usage: " << argv[0] << " signum pid" << std::endl;
return 1;
}
pid_t pid = std::stoi(argv[2]);
int signum = std::stoi(argv[1]);
kill(pid, signum);
}
raise函数
发信号给自己 == kill(getpid(), sig)
只能向当前进程发送信号

参数解释:
信号标号
返回值:成功返回0失败返回-1
#include <signal.h>
#include <stdio.h>
int main()
{
printf("raise befor.");
raise(9);//结束自己。相当于_exit
printf("raise after.\n");
return 0;
}
CLC@Embed_Learn:~/linux_io/02/02/seven$ ./a.out
Killed //并未打印出raise befor.,所以相当于_exit
信号处理函数:
abort函数

函数功能:使当前进程接收到信号而异常终止
参数:无参数
返回值:无返回值
void handler(int sig)
{
std::cout << "get a sig: " << sig << std::endl;
}
int main()
{
int cnt = 0;
signal(SIGABRT, handler);
while (true)
{
sleep(1);
std::cout << "hello bit, pid: " << getpid() << std::endl;
abort();
}
}

信号虽被捕捉,但abort正常接收终止进程






最低0.47元/天 解锁文章
2501






