### 信号是什么?
* 信号是一种很古老的IPC(进程间通信)方式。在早期的类Unix操作系统中,信号只能传递很简单的信息,即一个int(信号的编号)值。
* 信号是一种异步的消息传递方式或者说通知机制。
举一个不恰当的例子,你正在很兴奋地解决一个BUG,突然手机响了,女朋友说要分手。你立马放下手上的活,去处理女朋友那件事。手机随时都会响,随时都会中断你当下的事情。所以称之为异步事件。这个例子中的信号就体现在手机铃声响了。你去处理女朋友分手就是对信号做出的响应。
* 虽然信号是一种低级的IPC方式,但同时它保持了很简单的特性。在一些大型服务端程序中,很多时候也要考虑信号造成的影响。还是值得一学的。
从上面的例子可以看出,当产生一个信号(如:手机铃声响),之后就要去响应这个信号,如何响应这个信号则需要编程人员来写一个函数。当产生信号时,程序去执行之这个函数(如:处理女朋友分手)。
### Linux下信号分两种.
* 第一种: 用于内核向进程通知事件.即传统或者标准信号.(信号编号由1~31)
* 第二种: 实时信号(信号编号由34~64)
* 0号信号用来测试对应进程是否存在或者是否由权限给其发送信号
### 一般程序收到信号时进程的现象:
1. 忽略信号
2. 终止(杀死)进程
3. 产生核心转储文件,同时进程终止(核心转储文件即保存了程序跪掉的现场信息的文件,用来分析程序为何跪掉)。
4. 停止进程
5. 于之前暂停后再度恢复执行
### 编程可以做到的
1. 设置信号到来时采取默认的行为.
2. 忽略掉该信号.
3. 执行信号处理器程序.
### 常用信号类型即默认行为
|信号名称|产生的效果|对进程默认的效果|
|-----------|---------------------|----------------|
|SIGINT | Ctrl-C终端下产生|终止当前进程|
|SIGABRT|产生SIGABRT信号|默认终止进程,并产生core(核心转储)文件|
|SIGALRM|由定时器如alarm(),setitimer()等产生的定时器超时触发的信号|终止当前进程|
|SIGCHLD|子进程结束后向父进程发送| 忽略|
|SIGBUS|总线错误,即发生了某种内存访问错误|终止当前进程并产生核心转储文件|
|SIGKILL|必杀信号,收到信号的进程一定结束,不能捕获|终止进程|
|SIGPIPE|管道断裂,向已关闭的管道写操作|进程终止|
|SIGIO|使用fcntl注册I/O事件,当管道或者socket上由I/O时产生此信号|终止当前进程|
|SIGQUIT|在终端下Ctrl-\产生|终止当前进程,并产生core文件|
|SIGSEGV|对内存无效的访问导致即常见的“段错误”|终止当前进程,并产生core文件|
|SIGSTOP|必停信号,不能被阻塞,不能被捕捉|停止当前进程|
|SIGTERM|终止进程的标准信号 |终止当前进程|
0号信号用来测试对应进程是否存在或者是否有权限向对应进程发送该信号 (后面就理解了)
### 如何设计信号处理函数?
* 一般而言,信号处理函数设计的越简单越好,因为当前代码的执行逻辑被打断,最好尽快恢复到刚才被打断之前的状态。从而避免竞争条件的产生。
* 在信号处理函数中,建议不要调用printf等与I/O相关的函数。以及一些慢设备操作。这样会使得信号处理函数的执行时间变长,可能,操作系统就会切换其它程序去在CPU上执行。但如果有特殊需要,则也可以使用。
* 在信号处理函数中,不要使用任何不可重入的函数后面会说到。保证信号处理函数可以安全地执行完。并不会影响主逻辑执行。
### 信号的发送与处理
来简单看一个实例,看看信号最简单的使用方式(当键入Ctrl-C时候即程序收到SIGINT信号时进行处理。):
```C
// signal 的函数原型
// void (*signal(int sig , void (*func)(int)))(int);
// 至于这个怎么理解,这里就不再赘述了,请参考 《C Traps and Pitfalls》2.1节即理解函数声明。
// filename : simple_signal.cpp
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#define MSG "Catch signal SIGINT processing \n"
#define MSG_END "Finished process SIGINT return \n"
void do_too_heavy_work () {
long long s = 0 ;
for (long long i = 0 ; i < 500000000L ; i++ ) {
s += i ;
}
}
void sig_handler (int signuum ) {
// 本程序只是为了来进行演示,
// 在信号处理程序中,尽量不要调用与标准IO相关的和不可重入的函数。
write ( STDOUT_FILENO , MSG , strlen (MSG) ) ;
do_too_heavy_work();
write ( STDOUT_FILENO , MSG_END , strlen (MSG_END) ) ;
}
int main() {
// 注册信号处理函数
if ( SIG_ERR == signal ( SIGINT , sig_handler ) ) {
fprintf (stderr , "signal error ") , perror ("") ;
exit (1) ;
}
// 让主程序不退出,挂起,等待信号产生
while (1) {
pause () ;
}
return EXIT_SUCCESS ;
}
```
程序会一直停着等待用户行为。当我们键入Ctrl-C时程序打印相关信息,之后程序自己退出。那么程序的执行流程就类似这样:
```shell
[tutu@localhost Linux-Book]$ gcc simple_signal.cpp
[tutu@localhost Linux-Book]$ ./a.out
^CCatch signal SIGINT processing
Finished process SIGINT return
^CCatch signal SIGINT processing
Finished process SIGINT return
^CCatch signal SIGINT processing
Finished process SIGINT return
```
这是一种古老的注册信号并设置信号处理函数的方式。现在我们使用新的信号注册函数即sigaction函数。它提供了更多的控制字段(旧的signal已经使用sigaction进行了实现。祥见glibc源码,我自己的Fedora 22 glibc 版本2.21可以在glibc官网[Glibc](http://ftp.gnu.org/gnu/glibc/)下载Glibc源码,对应路径下glibc/glibc-2.21/sysdeps/posix/signal.c看到)包括屏蔽信号集,设置高级信号处理函数等(稍后会详细讲述,别担心).
#### 为什么不是用signal来进行信号注册了?
* signal 无法设置在执行信号处理程序时要屏蔽哪些信号的产生。
* signal 函数注册的信号处理函数只能携带很少的信息(也不常用),在信号处理函数进行信号处理时。
* signal 无法设置一些标志位来执行一些动作(后面再讲)。
* signal 只能设置所给信号的处理方式但sigaction还可以获取之前这个信号的处理方式
#### 废话这么多,大家都嫌弃了,来一个真实的例子吧,和上面的程序功能一样,但是使用sigaction进行处理。
```C
// filename : simple_sigaction.cpp
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
#include <fcntl.h>
#define MSG "Catch signal SIGINT processing \n"
#define MSG_END "Finished process SIGINT return \n"
void do_too_heavy_work () {
long long s = 0 ;
for (long long i = 0 ; i < 500000000L ; i++ ) {
s += i ;
}
}
void sig_handler (int signuum ) {
// 本程序只是为了来进行演示,
// 在信号处理程序中,尽量不要调用与标准IO相关的,不可重入的函数。
write ( STDOUT_FILENO , MSG , strlen (MSG) ) ;
do_too_heavy_work();
write ( STDOUT_FILENO , MSG_END , strlen (MSG_END) ) ;
}
int main() {
// 注册信号处理函数
struct sigaction newact ;
// 将信号处理函数执行期间掩码设置为空
sigemptyset (&newact.sa_mask ) ;
// 将标志设置为0即默认
newact.sa_flags = 0 ;
// 注册信号处理函数
newact.sa_handler = sig_handler ;
if ( 0 > sigaction ( SIGINT , &newact , NULL ) ) {
fprintf (stderr , "sigaction error ") , perror ("") ;
exit (1) ;
}
// 让主程序不退出,挂起,等待信号产生
while (1) {
pause () ;
}
return EXIT_SUCCESS ;
}
```
执行效果和刚才的一样,在这里就不再贴过来了。
#
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
所有源码均经过严格测试,可以直接运行,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答!Linux系统是一个免费使用和自由传播的类Unix操作系统,基于POSIX和UNIX的多用户、多任务、支持多线程和多CPU的操作系统。它继承了Unix以网络为核心的设计思想,是一个性能稳定的多用户网络操作系统,Linux是许多企业和服务提供商的首选操作系统,用于部署Web服务器、数据库服务器、邮件服务器等。Linux系统具有高效的网络功能和稳定的性能,因此被广泛应用于服务器领域,Linux是云计算的核心组成部分,被广泛用于构建云平台和云服务。许多知名的云计算服务提供商都采用Linux系统作为其基础架构,一些游戏平台和游戏开发工具采用Linux作为支持的操作系统,例如Steam平台上的某些游戏。Linux系统在科学计算、数据分析和机器学习等领域也有广泛应用。许多知名的科学计算软件都在Linux上开发和运行,Linux系统在各个领域都有广泛的应用,其强大的功能和灵活性使得它成为许多产品和服务的基础架构。
资源推荐
资源详情
资源评论
收起资源包目录
linux系统编程指南.zip (63个子文件)
1.1
system-call
chapter-8
README.md 32B
chapter-6
sigqueue_post_signal.cpp 753B
kill_SIGRTMIN.sh 130B
simple_realiable_signal.cpp 952B
simple_sigaction.cpp 1KB
sig_flag.cpp 2KB
sigqueue_wait.cpp 889B
simple_signal.cpp 946B
README.md 27KB
chapter-2
OpenReadWriteAndCloseFile.md 5KB
overview.md 1KB
images
vfs.png 23KB
README.md 1KB
chapter-5
thread_create.md 5KB
producer_consumer.md 28B
thread_mutex.md 12KB
linux-thread-history.md 12KB
thread_overview.md 5KB
images
linux-thread-history
9.png 17KB
3.png 42KB
1.png 26KB
6.png 112KB
5.png 59KB
4.png 164KB
8.png 15KB
7.png 35KB
2.png 11KB
time_mutex.png 9KB
thread_create.png 8KB
asm_add.png 10KB
process.png 51KB
thread_add.png 18KB
README.md 3KB
chapter-7
README.md 32B
chapter-3
aboutbss.md 2KB
process_memory.md 7KB
c_mem_eg.md 3KB
chap_3_code
test.c 310B
C_mem.o 2KB
C_mem.c 498B
C_mem 10KB
first_process_init.md 1KB
dir.md 471B
images
Cmem.png.png 11KB
C_mem.png.png 31KB
testo.png 54KB
process_mem_picture (1).png 22KB
test.png 11KB
size_c_mem.png 24KB
process_mem_picture.png 22KB
C_mem_objdump.png 52KB
testc.png 16KB
README.md 32B
chapter-1
os&syscall.md 4KB
system_call_error.md 4KB
linux_syacall&windows_api.md 3KB
README.md 2KB
code_format.md 1KB
chapter-4
README.md 32B
SUMMARY.md 3KB
README.md 295B
kernel
chapter-1
README.md 32B
SUMMARY.md 71B
共 63 条
- 1
资源评论
妄北y
- 粉丝: 2w+
- 资源: 1万+
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
- 鸟类目标检测数据集-含画眉鸟-百灵鸟xml文件数据集
- pyheif-0.8.0-cp37-cp37m-win-amd64.whl.zip
- 基于深度学习的鸟类种类目标检测-含数据集和训练代码-对百灵鸟-画眉鸟检测.zip
- pyheif-0.8.0-cp38-cp38-win-amd64.whl.zip
- pyheif-0.8.0-cp39-cp39-win-amd64.whl.zip
- pyheif-0.8.0-cp313-cp313-win-amd64.whl.zip
- MyBatis SQL mapper framework for Java.zip
- pyheif-0.8.0-cp312-cp312-win-amd64.whl.zip
- pyheif-0.8.0-cp311-cp311-win-amd64.whl.zip
- pyheif-0.8.0-cp310-cp310-win-amd64.whl.zip
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功