关闭

探秘C-signal信号

147人阅读 评论(0) 收藏 举报

探秘C程序中的信号

简单的不多说,也就不进行简单的介绍了。

可移植性:

首先对于<signal.h>中声明的函数不能完全的安全的定义一种可移植的用法,原则上,可以为一个只有raise报告的信号指定一个处理程序,但是很难想象它的那些方面比<setjmp.h>中的跳转函数做得更好,同时也不能保证一个指定的信号在C语言的所有实现中不可能报告,所以不管什么时候程序处理信号,它的可移植性都会受到限制。

C标准库关于信号的一些内容:

在头文件<signal.h>为处理各种各样的信号声明了一个类型和两个函数,并定义了几个宏。

定义类型:

sig_atomic_t  :这个类型的对象可以作为一个原子实体被访问,即使有异步中断发生的时候也是如此。

定义的宏:

SIG_DFL

SIG_ERR

SIG_IGN

这个三个宏展开为具有不同值的常量表达式,且他们的值和所有声明的函数的地址都不相等,下面还有几个宏,都展开为正的数值常数表达式,他们主要针对具体的情况对应的信号。

SIGABRT    异常终止,例如调用了abort()函数

SIGFPE       错误的算术操作,除0或溢出,现在广泛的所有的溢出都报告这个信号

SIGILL        一条无效的函数影像

SIGINT        收到一个交互的提示信号,异步可中断原子操作,若未保存上下文,无法恢复执行

SIGSEGV     对存储器的无效访问,段越界,就是段错误的信号

SIGTERM     送到程序中的终止请求

 

定义的函数

#include <signal.h>

typedef void (*sighandler_t)(int);

sighandler_t signal(int signum, sighandler_t handler);        /*信号处理函数*/

int raise(int sig);                                        /*信号发送函数*/

<signal.h>的实现

这里我们依然是为了探秘原理,做一个简单的小例子。

首先说一下硬件信号吧。

硬件信号和我们其他一些软件信号是不同的,在某些系统中,有些代码需要得到控制权,由于这是异步的所以会选择将这些代码添加进signal 中。所以硬件系统或者计算机本身报告的信号,所以这里一定要小心。很多系统都会把控制权转移到指定的地址,但不会遵守C函数调用和返回的规则,所以处理这些每一个信号都必须使用一些汇编代码。

来硬性的告诉操作系统,这些代码需要得到控制权,此时会从这些静态的代码中获取权限。然后执行。

我们这里的着眼点主要聚焦于软件层面上。

[c]

#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
#include<signal.h>
#include<string.h>
#include<stdlib.h>

typedef int sig_atomic_t ;
typedef void _sigfun(int);

_sigfun *_sigtable[_NSIG] = {0};

int (raise)(int sig){
_sigfun *s;
if(sig <= 0 || _NSIG <= sig)
return (-1);
if((s = _sigtable[sig]) != SIG_IGN && s != SIG_DFL)
{
_sigtable[sig] = SIG_DFL;
(*s)(sig);
}else if(s == SIG_DFL){
char ac[10],*p;
switch(sig){
case SIGABRT:
p = "abort";
break;
case SIGFPE:
p = "arithmetic error";
break;
case SIGILL:
p = "invaild executable code";
break;
case SIGSEGV:
p = "termination request";
break;
default :
*(p = &ac[(sizeof ac)-1]) = '\0';
do{
*--p = sig %10 + '0';

}while((sig /= 10) != 0);
fputs("signal #",stderr);
}
fputs(p,stderr);
fputs("----terminating \n",stderr);
exit(EXIT_FAILURE);
}
return 0;
}

_sigfun * (signal)(int sig,_sigfun *fun)
{
_sigfun *s;
if(sig <= 0 || _NSIG <= sig || fun == SIG_ERR)
return (SIG_ERR);
s = _sigtable[sig];
_sigtable[sig] = fun;
fun(sig);
return (s);
}

void signalfun(int sig){
printf("I get the signal and take it\n");
return ;
}
int main(){
signal(SIGINT,signalfun);
kill(getpid(),SIGINT);

}

[/c]

查看原文:http://zmrlinux.com/2015/11/20/%e6%8e%a2%e7%a7%98c-signal%e4%bf%a1%e5%8f%b7/

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:68047次
    • 积分:3058
    • 等级:
    • 排名:第11382名
    • 原创:244篇
    • 转载:6篇
    • 译文:0篇
    • 评论:13条
    最新评论