signal原型分析

来源:互联网 发布:淘宝鞋子试用报告 编辑:程序博客网 时间:2024/06/05 09:56

在linux-0.11内核中,我们找到signal函数原型:

void (*signal(int _sig, void (*_func)(int)))(int);

这个函数很难理解,先复习看一些基础知识。


1、函数指针定义

int  (*f)(int);                     //定义f为   有一个int类型参数,返回值为int的  函数指针

int p(int); // 我们可以通过 f = &p; 对f进行赋值。

char ( *pf(long) )(int) {}        //定义pf为有一个long类型参数,返回值为(有一个int类型参数,返回值为char类型函数指针)  的函数     


那么void (*signal(int _sig, void (*_func)(int)))(int); 

即是 声明了一个带有2个参数,返回值为带有一个int类型参数,返回值为void的函数指针 的函数


2、通过小例子进一步学习

#include <stdio.h>void pt(int){printf("2\n");}void (*f(int, void (*fun)(int)))(int){return fun;}int main(){f(0, pt);printf("----\n");(*f(0, pt))(0);}
这个小程序的输出为:


f(0, pt); 调用后,返回fun的地址,即将fun的地址推送到eax, 但是并未执行。

(*f(0, pt))(0); 调用后, 将eax的地址作为一个函数进行调用, 所以这样的输出就不难理解了。


3、signal源码分析

signal通过int0x80调用系统中断sys_signal. 实现和上面的f基本一样, 其实f就是signal的简化版。

int sys_signal(int signum, long handler, long restorer){struct sigaction tmp;if (signum<1 || signum>32 || signum==SIGKILL)return -1;tmp.sa_handler = (void (*)(int)) handler;tmp.sa_mask = 0;tmp.sa_flags = SA_ONESHOT | SA_NOMASK;tmp.sa_restorer = (void (*)(void)) restorer;handler = (long) current->sigaction[signum-1].sa_handler;current->sigaction[signum-1] = tmp;return handler;}
这个函数将signal(SIG_NUM, handle)传递的参数在进程上下文(信号处理表)中进行注册, 同时返回旧的handle地址。

该函数和上面的f一样,只是将handle地址存放到eax寄存器,当做调用的返回, 并未实际执行函数。


4、更好的方法

typedef void (*__sighandler_t) (int);       

//引入 __sighandler_t   类型    为 一个带int类型参数,返回值为void的函数指针     的关键字


extern __sighandler_t __sysv_signal (int __sig, __sighandler_t __handler)       

 //声明一个返回值为函数指针的函数



1 0
原创粉丝点击