【VS开发】程序如何捕捉signal函数参数中指定的信号
当说到signal的功能时,我们都知道它会捕捉我们所指定的信号,然后调用我们所指定的信号处理函数。但它是如何捕捉我们指定的信号的呢?下面我就以msdn上关于signal的example为例,说明signal是如何捕捉信号的。
程序如下:
[cpp] view plain copy
// crt_signal.c
// compile with: /c
// Use signal to attach a signal handler to the abort routine
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <tchar.h>
void SignalHandler(int signal)
{
printf("Application aborting...\n");
}
int main()
{
typedef void (*SignalHandlerPointer)(int);
SignalHandlerPointer previousHandler;
previousHandler = signal(SIGABRT, SignalHandler);
abort();
}
先说一下signal函数的声明:void (*signal(int sig,void (*func)(int)))(int),它的返回值类型是函数指针,这个函数指针指向一个返回值为void类型,接受一个int参数的函数。实际上signal函数返回的是该函数调用前指定信号的处理函数的指针。
回到程序中来,这个程序很简单,首先定义了一个信号处理函数SignalHandler,然后调用signal用SignalHandler处理所产生的中止信号(SIGABRT)。执行程序时,首先调用signal函数,signal函数的定义(winsig.c中)部分如下:
[cpp] view plain copy
_PHNDLR __cdecl signal(int signum,_PHNDLR sigact)
{
//...
switch (signum) {
case SIGINT:
//...
break;
case SIGBREAK:
//...
break;
case SIGABRT:
case SIGABRT_COMPAT:
oldsigact = (_PHNDLR) DecodePointer(abort_action);
if(sigact!=SIG_GET)
{
abort_action = (_PHNDLR) EncodePointer(sigact);
}
break;
case SIGTERM:
//...
break;
}
//...
}
我们可以看到,指定了SIGABRT,signal函数就会执行case SIGABRT下面的语句,将指向函数调用前的SIGABRT处理函数的指针赋给oldsigact,将新的处理函数编码后赋给abort_action,这一步非常重要,因为下面的abort()函数就是根据它来得到信号处理函数的。
接下来执行abort函数,该函数会产生SIGABRT信号,其定义(abort.c中)如下:
[cpp] view plain copy
void __cdecl abort (
void
)
{
_PHNDLR sigabrt_act = SIG_DFL;
//...
sigabrt_act = __get_sigabrt();
if (sigabrt_act != SIG_DFL)
{
raise(SIGABRT);
}
//...
_exit(3);
}
该函数调用__get_sigabrt()取得信号处理函数sigabrt_act,然后调用raise(SIGABRT),在这个函数中调用信号处理函数。raise()的定义()如下:
[cpp] view plain copy
int __cdecl raise (
int signum
)
{
_PHNDLR sigact;
_PHNDLR *psigact;
switch (signum) {
case SIGINT:
sigact = *(psigact = &ctrlc_action);
siglock++;
break;
case SIGBREAK:
sigact = *(psigact = &ctrlbreak_action);
siglock++;
break;
case SIGABRT:
case SIGABRT_COMPAT:
sigact = *(psigact = &abort_action);
siglock++;
break;
case SIGTERM:
sigact = *(psigact = &term_action);
siglock++;
break;
case SIGFPE:
case SIGILL:
case SIGSEGV:
ptd = _getptd_noexit();
if (!ptd)
return (-1);
sigact = *(psigact = &(siglookup( signum,
ptd->_pxcptacttab )->XcptAction));
goto decode_done;
break;
default:
/*
* unsupported signal, return an error
*/
_VALIDATE_RETURN(("Invalid signal or error", 0), EINVAL, -1);
}
sigact = (_PHNDLR) DecodePointer(sigact);
decode_done:
/*
* If the current action is SIG_IGN, just return
*/
if ( sigact == SIG_IGN )
return(0);
/*
* If the current action is SIG_DFL, take the default action
*/
if ( sigact == SIG_DFL ) {
_exit(3);
}
//...
(*sigact)(signum);
return(0);
}
在case SIGABRT中将abort_action的值即信号处理函数指针赋给sigact,在最后调用函数(*sigact)(signum)完成对SIGABRT信号的处理。程序对其他信号的捕捉过程也差不多是这样。
在我这里说的只是一个大概的流程,其中还有很多代码的细节没有涉及到,比如说对预定义的信号处理函数的判断、异常的处理等,这些还有待深入理解和研究。
顶
【VS开发】程序如何捕捉signal函数参数中指定的信号的更多相关文章
- Python函数参数中的冒号与箭头
在一些Python的工程项目中,我们会看到函数参数中会有冒号,有的函数后面会跟着一个箭头,你可能会疑惑,这些都是什么东西? 其实函数参数中的冒号是参数的类型建议符,告诉程序员希望传入的实参的类型.函数 ...
- python函数参数中带有默认参数list的坑
在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 def f(x,l=[]): for i in range(x): l.append(i*i) print(l) print( ...
- (转)python中函数参数中如果带有默认参数list的特殊情况
在python中函数参数中如果带有默认参数list遇到问题 先看一段代码 1 2 3 4 5 6 7 8 9 def f(x,l=[]): for i in range(x): ...
- 关于cmp函数参数中的&符号
关于cmp函数参数中的&符号 关于sort函数中的cmp函数有着不同的写法,以刚刚的整形元素比较为例 还有人是这么写的: bool cmp(const int &a, const in ...
- 错误“Sources”参数中指定了多次。“Sources”参数不支持重复项。
在“Sources”参数中指定了项“”多次.“Sources”参数不支持重复项. Asp.Net关于错误“Sources”参数中指定了多次.“Sources”参数不支持重复项. “Sources”参数 ...
- PowerShell控制台输出符号+函数参数类型指定+文本内容读取
There are several ways: Write-Host: Write directly to the console, not included in function/cmdlet o ...
- Linux下利用signal函数处理ctrl+c等信号
前言 linux下能够通过信号机制来实现程序的软中断,是一个很实用的编程方法. 我们平时在程序执行的时候按下ctrl-c.ctrl-z或者kill一个进程的时候事实上都等效于向这个进程发送了一个特定信 ...
- Delphi 中 函数参数中的 const 修饰符的本质以及注意事项
来自:http://blog.csdn.net/farrellcn/article/details/9096787 ------------------------------------------ ...
- 通过java程序调用ant build.xml配置文件中指定的target
一.概述 通过ant实现项目的自动化部署,jar包生成,替换,tomcat关停.启动,查看项目日志: 通过java程序调用已编辑好的ant脚本build.xml配置文件中指定的target: 文中文件 ...
随机推荐
- RookeyFrame 信息 常用信息整理
博客 https://www.cnblogs.com/rookey/ gitee的地址: https://gitee.com/rookey/Rookey.Frame-v2.0 https://gite ...
- UOJ46 【清华集训2014】玄学 【时间线段树】
题目链接:UOJ 这题的时间线段树非常的妙. 对时间建立线段树,修改的时候在后面加,每当填满一个节点之后就合并进它的父亲. 对于一个节点维护序列,发现这是一个分段函数,合并就是归并排序.于是就形成了差 ...
- UOJ422. 【集训队作业2018】小Z的礼物 [min-max容斥,插头DP]
UOJ 思路 由于没有代码和AC记录的支撑,以下思路可能有错. 看到全部取完,大概可以想到min-max容斥. 由于期望的表达式里面合法方案的个数是在分母里面的,所以可以想到把它记录在状态里. 然而由 ...
- js 中的方法注入(aop)
js 中的方法注入 java中很多框架支持 apo 的注入, js中也可以类似的进行实现 主要是通过扩展js中方法的老祖 Function 对象来进行实现. Function.prototype.af ...
- 《挑战30天C++入门极限》新手入门:C/C++中的结构体
新手入门:C/C++中的结构体 什么是结构体? 简单的来说,结构体就是一个可以包含不同数据类型的一个结构,它是一种可以自己定义的数据类型,它的特点和数组主要有两点不同,首先结构体可以在一个结构 ...
- Loadrunner录制+运行+结果-【飞机订票系统实战】
目录结构: 一.LoadRunner实现订票系统脚本录制 二.Loadrunner实现订票系统IP欺骗(此处可以不设置) 三.Loadrunner运行录制的脚本 四.Load generator配置 ...
- book-rev8
xv6 a simple, Unix-like teaching operating system 一个简易.类Unix教学操作系统 Russ Cox Frans Kaashoek Robert Mo ...
- ubuntu16.04安装opencv3.4.1教程
最近opencv3.4.1发布了,想换个新的试试鲜,于是把配置的过程通过博文的方式记录下来,方便查阅. 本教程原为3.3.0,但经过博主亲测,3.4.0.3.4.1皆适用 1.去官网下载opencv, ...
- 苹果IPhone真机开发调试
需要 在苹果开发网站 加入真机的UDID, 并在Profile中勾选该手机
- SSM项目启动报错WEB-INF\lib\javax.servlet-api-4.0.1.jar) - jar not loaded. See Servlet Spec 3.0, section 10
错误信息: validateJarFile(D:\tomcat_ryxunit\webapps\ryx_unit\WEB-INF\lib\javax.servlet.jar) - jar not lo ...