Linux:进程信号

生活角度的信号

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正常接收终止进程

signal函数


                
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

你好,赵志伟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值