signal原型分析

在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
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值