linux信号

信号是一种类似IRQ的机制,提供了一种非常美妙的处理异步事件的方式,所以又称软件中断。

因为信号是随机出现的,出现时机不会为进程提前预测,所以对于信号的处理需要预先设定给kernel,要求kernel按照以下三种方式中的一个来处理。

1,忽略此信号,这也是大部分信息的处理方式,但是SIGKILL和SIGSTOP信号不可忽略。

2,捕捉信号,提前通知内核在某种信号发生时调用一个用户函数,做定制处理。

3,执行系统默认动作,系统对于每个内核信号(linux共有31个)都有一个默认操作。


信号处理函数最初函数原型为:void ( *signal (int signo, void (*func)(int) )  ) (int);

linux man page是这么描述这个函数原型的:


这个函数看起来灰常蛋疼,刚毕业的时候看linux源码剖析,C语言基础不好,当日情景,历历在目。

此函数需要两个参数,返回一个函数指针,该指针指向的函数无返回值。第一个参数signo是一个整数,第二个是一个函数指针,其指向函数需要一个int参数且返回void,也即这个函数指针跟signal函数返回的函数地址的函数是一样的。好吧,我觉得我说的自己都晕了。

因其太过难以理解,所以后来被改造:

假如typedef  void sighandler(int)

sighandler *signal(int, sighandler)就可以代替上述函数原型。

系统头文件中声明了三个宏:

#define SIG_ERR        (void (*)()) -1

#define SIG_DFL        (void (*)())  0

#define SIG_IGN         (void (*)())  1

这几个宏可以用于signal函数的第二个函数和返回值。

下面来看一个signal的实例,用信号来实现一个软件定时器:

static timer = 0;
void timer_proc(sigid){
	if(timer)
		timer--;
	return;
}

void set_time_ms(void)
{
	struct itimerval v;

	if(signal(SIGALRM,timer_proc) == SIG_ERR)
	{
		printf("signal handler config error\n");
	}
	
	v.it_interval.tv_sec = 0;
	v.it_interval.tv_usec = 97000;
	v.it_value.tv_sec = 0;
	v.it_value.tv_usec = 97000;
	(void)setitimer(ITIMER_REAL, &v, NULL);
	
	while(1)
	{
		pause();
	}
}
被信号中断的系统调用:


kill和raise函数:

#include <signal.h>
int kill(pid_t pid, int signo);
int raise(int signo);
//raise(signo) 等价于 kill(getpid(), signo)
这两个函数的主要功能是发送一个信号来终结进程。

对于kill的pid参数有4种不同的情况:

pid > 0,正常将信号发送给ID为pid的进程。

pid = 0,将该信号发送给与发送进程属于同一进程组的所有进程,前提是发送进程有词权限。

pid < 0,将信号发送给进程组ID为pid的绝对值,需要权限。

pid = -1,将信号发送给发送进程所有有权限发送的进程。

shell命令的kill就是通过这个系统调用实现的。


alarm和pause函数:

#include <unistd.h>
unsigned int alarm(unisigned int seconds);
alarm函数可以设置一个计时器,计时器超时时会产生SIGALRM信号,如果不忽略或不捕捉该信号,默认动作为此函数调用者退出。

每个进程只能有一个闹钟时钟,如果旧的未超时,新的会更新计时器,并将旧的剩余时间通过返回值返回。

所以可以通过alarm(0)来关闭定时器。

#include <unistd.h>
int pause(void);
pause()挂起一个进程直到捕捉一个信号。只有执行了一个信号处理并返回时,pause才返回。返回-1,并将errno设置为EINTR。













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值