Linux:Linux进程信号

✨✨✨学习的道路很枯燥,希望我们能并肩走下来!

文章目录

目录

文章目录

前言

一  信号快速认识 

1.1  生活角度的信号

1.2  技术应用角度的信号 

 1.2.1  样例代码

1.2.2  系统函数signal 

1.3 信号概念 

1.3.1  查看信号 

​编辑1.3.2  信号处理

二  产生信号 

​编辑2.1 通过终端按键产⽣信号

2.1.1 基本操作 

2.1.2 理解OS如何得知键盘有数据 

​编辑 2.1.3 初步理解信号起源

 2.2 调⽤系统命令向进程发信号

2.3 使⽤函数产⽣信号 

2.3.1  kill

​编辑2.3.2  raise

2.3.3  abort

​编辑2.4  由软件条件产⽣信号

2.4.1 基本alarm验证-体会IO效率问题 

​编辑 2.4.2 设置重复闹钟

 2.4.3 如何理解软件条件

2.4.4 如何简单快速理解系统闹钟 

2.5 硬件异常产⽣信号 

​编辑 2.5.1  除以0

2.5.2  野指针 

2.5.3 ⼦进程退出core dump 

2.5.4 Core Dump 

2-6 总结思考 

三  保存信号

​编辑3.1 信号其他相关常⻅概念

3.2 在内核中的表示

3.3 sigset_t 

3.4 信号集操作函数 

3.4.1  sigprocmask

3.4.2  sigpending 

​编辑四  捕捉信号

​编辑 4-1 信号捕捉的流程

​编辑 4.2 sigaction

4-3 穿插话题-操作系统是怎么运⾏的 

4-3-1 硬件中断 

4.3.2 时钟中断 

4.3.3 死循环 

 4.3.4 软中断

​编辑 4.3.5 缺⻚中断?内存碎⽚处理?除零野指针错误?

4.4 如何理解内核态和用户态 

五  可重入函数 

六  volatile 

七  SIGCHLD信号(了解)


前言

本篇详细介绍了进一步介绍Linux的进程间通信,让使用者有更加深刻的认知,而不是仅仅停留在表面,更好的模拟,为了更好的使用. 文章可能出现错误,如有请在评论区指正,让我们一起交流,共同进步!


一  信号快速认识 

1.1  生活角度的信号

• 你在⽹上买了很多件商品,再等待不同商品快递的到来。但即便快递没有到来,你也知道快递来临 时,你该怎么处理快递。也就是你能“识别快递”

• 当快递员到了你楼下,你也收到快递到来的通知,但是你正在打游戏,需5min之后才能去取快递。 那么在在这5min之内,你并没有下去去取快递,但是你是知道有快递到来了。也就是取快递的⾏为 并不是⼀定要⽴即执⾏,可以理解成“在合适的时候去取”。

• 在收到通知,再到你拿到快递期间,是有⼀个时间窗⼝的,在这段时间,你并没有拿到快递,但是 你知道有⼀个快递已经来了。本质上是你“记住了有⼀个快递要去取”

• 当你时间合适,顺利拿到快递之后,就要开始处理快递了。⽽处理快递⼀般⽅式有三种:1.执⾏默 认动作(幸福的打开快递,使⽤商品)2.执⾏⾃定义动作(快递是零⻝,你要送给你你的⼥朋友) 3. 忽略快递(快递拿上来之后,扔掉床头,继续开⼀把游戏)

• 快递到来的整个过程,对你来讲是异步的,你不能准确断定快递员什么时候给你打电话

1.2  技术应用角度的信号 

 1.2.1  样例代码

// sig.cc
#include <iostream>
#include <unistd.h>
int main()
{
	while (true) {
		std::cout << "I am a process, I am waiting signal!" << std::endl;
		sleep(1);
	}
}
$ g++ sig.cc - o sig
$ . / sig
I am a process, I am waiting signal!
I am a process, I am waiting signal!
^C

• ⽤⼾输⼊命令,在Shell下启动⼀个前台进程

• ⽤⼾按下 程 Ctrl+C ,这个键盘输⼊产⽣⼀个硬件中断,被OS获取,解释成信号,发送给目标前台进程

• 前台进程因为收到信号,进⽽引起进程退出(退出前台进程) 

1.2.2  系统函数signal 

#include <iostream>
#include <unistd.h>
#include <signal.h>

void handler(int signumber)
{
	std::cout << "我是: " << getpid() << ",我获得了⼀个信号: " << signumber << endl;
}

int main()
{
	std::cout << "我是进程: " << getpid() << std::endl;
	signal(SIGINT/*2*/, handler);
	while (true) {
		std::cout << "I am a process, I am waiting signal!" << std::endl;
		sleep(1);
	}
}

 

注意:

• 要注意的是,signal函数仅仅是设置了特定信号的捕捉⾏为处理⽅式,并不是直接调⽤处 理动作。如果后续特定信号没有产⽣,设置的捕捉函数永远也不会被调⽤!! 

• Ctrl+C 产⽣的信号只能发给前台进程。⼀个命令后⾯加个&可以放到后台运⾏,这样 Shell不必等待进程结束就可以接受新的命令,启动新的进程。

• Shell可以同时运⾏⼀个前台进程和任意多个后台进程,只有前台进程才能接到像 Ctrl+C 这种控制键产⽣的信号。

• 前台进程在运⾏过程中⽤⼾随时可能按下 Ctrl-C Ctrl-C ⽽产⽣⼀个信号,也就是说该进程的⽤⼾空间代码执⾏到任何地⽅都有可能收到 SIGINT 信号⽽终⽌,所以信号相对于进程的控制流程来说是异步(Asynchronous)的。

• 关于进程间关系,我们在⽹络部分会专⻔来讲,现在就了解即可。

• 可以渗透&和nohup 

1.3 信号概念 

信号是进程之间事件异步通知的⼀种⽅式,属于软中断。 

1.3.1  查看信号 

 每个信号都有⼀个编号和⼀个宏定义名称,这些宏定义可以在signal.h中找到,例如其中有定义

#define SIGINT 2 

 编号34以上的是实时信号,本章只讨论编号34以下的信号,不讨论实时信号。这些信号各⾃在什么条件 下产⽣,默认的处理动作是什么,在signal(7)中都有详细说明:         man 7 signal

1.3.2  信号处理

(sigaction函数稍后详细介绍),可选的处理动作有以下三种: 

1. 忽略此信号

2. 执⾏该信号的默认处理动作

3.  提供⼀个信号处理函数,要求内核在处理该信号时切换到⽤⼾态执⾏这个处理函数,这种⽅式称为⾃定义捕捉(Catch)⼀个信号。 

 注意看源码:

#define  SIG_DFL   ((__sighandler_t)  0)  /* Default action.  */
#define  SIG_IGN   ((__sighandler_t)  1)  /* Ignore signal.  */

 /* Type of a signal handler.  */
 typedef void (*__sighandler_t) (int);

// 其实SIG_DFL和SIG_IGN就是把0,1强转为函数指针类型

二  产生信号 

2.1 通过终端按键产⽣信号

2.1.1 基本操作 

• Ctrl+C(SIGINT) 已经验证过,这⾥不再重复 

• Ctrl+\(SIGQUIT)可以发送终⽌信号 并⽣成coredump⽂件,⽤于事后调试(后⾯详谈)

• Ctrl+Z(SIGTSTP)可以发送停⽌信号,将当前前台进程挂起到后台等。

2.1.2 理解OS如何得知键盘有数据 

 2.1.3 初步理解信号起源

注意:

• 信号其实是从纯软件⻆度,模拟硬件中断的⾏为

• 只不过硬件中断是发给CPU,⽽信号是发给进程

• 两者有相似性,但是层级不同,这点我们后⾯的感觉会更加明显 

 2.2 调⽤系统命令向进程发信号

#include <iostream>
#include <unistd.h>
#include <signal.h>
int main()
{
	while (true) {
		sleep(1);
	}
}

首先在后台执⾏死循环程序,然后⽤kill命令给它发SIGSEGV信号。 

 

2.3 使⽤函数产⽣信号 

2.3.1  kill

kill命令是调用kill函数执行的,kill函数可以给⼀个指定的进程发送指定的信号。

评论 38
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值