1、 定时信号SIGALRM的用途

在编程的过程中,很多时候我们需要为程序设置一个闹钟,然后到了闹钟设定的时刻然后再去采取相关的操作。比如进行socket编程时,如果客户端长时间没有与服务器进行交互,需要服务器在一定时间之后主动关闭socket连接。在这种场景下,就可以在服务器收到客户端的socket的连接时,设置一个定时信号,然后在定时信号到来时,关闭掉socket连接即可。

2、定时信号SIGALRM的触发

通过alarm函数触发定时信号,在linux系统中,alarm函数需要的头文件为:

#include <unistd.h>

函数原型如下:

unsigned int alarm(unsigned int seconds)
/* 
参数:
	seconds:表示在当前时刻seconds秒之后产生一个SIGALRM信号,若seconds=0,表示取消闹钟
返回值:
0或者一个大于0的值。若值大于0,表示上一个定时器还剩余多少秒。比如:
int ret1 = alarm(10);    // 第0秒时刻,设定一个定时闹钟,准备10秒后触发SIGALRM信号, 此时返回值为0
sleep(5);
int ret2 = alarm(20); // 重新设定闹钟,定时信号将会在第25秒触发,此时ret2=5,表示上个闹钟还剩余5秒
*/

几点说明:

  • 闹钟信号只会触发一次,若想循环触发,可以在闹钟到时后重新通过alarm函数触发
  • 可以重新设置闹钟信号,即在上一个闹钟到时之前,通过alarm函数重新设定响铃时刻或取消闹钟

3、定时信号的响应与捕捉

3.1 系统默认对SIGALRM信号的响应

如果不对SIGALRM信号进行捕捉或采取措施,默认情况下,闹钟响铃时刻会退出程序。观察下面的程序:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
int main() {
  	int t = alarm( 5 );   // 设定闹钟5秒之后响铃
  	printf("set alarmer: %d \n", t);
  	sleep(2);
  	int ret = alarm(4);   // 重新设定闹钟4秒之后响铃,上一个闹钟还剩3秒
  	printf("reset alarmer: %d \n", ret);
   	int i;
	for ( i = 0; i < 15; i++ )
	{
	  	printf( " sleep % d ... \n ", i );
		sleep( 1 );
	}
	return 0;
}

打印如下:
在这里插入图片描述
从上面可以看到,重新设定闹钟在4秒之后响铃,4秒之后,屏幕打印:Alarm clock,
然后程序就退出了。

3.2 设置SIGALRM信号的响应函数

既然设定闹钟信号,肯定是希望在闹钟响铃的时刻采取一定的操作,这个操作自然是通过执行某个函数来实现。因此,我们需要为SIGALRM信号设定一定响应函数(回调函数),然后响铃的时候就会执行该函数。
信号回调函数的设置是通过sinal函数来进行的。需要对头文件为signal.h,signal.h是C标准函数库中的信号处理部分,定义了程序执行时如何处理不同的信号。函数原型如下:

// 位于头文件 signal.h
// Type of a signal handler
typedef void (*__sighandler_t)(int);
__sighandler_t signal(int __sig, __sighandler_t __handler);
/*
入参:
	__sig:表示要捕捉的信号,如果要捕捉SIGALRM信号,这里填SIGALRM即可
	__handler:回调函数(其实还可以设置其它值,具体见参考文章1)
返回值:
	返回指向回调函数的函数指针,若有错误则返回SIG_ERR	(-1)
*/

示例如下:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
 
/*闹钟信号处理函数*/
void sig_handler() {
	printf( "hello world! \n " );
}
int main() {
	signal( SIGALRM, sig_handler );
  	int t = alarm( 5 );
  	printf("set alarmer: %d \n", t);
  	sleep(2);
  	int ret = alarm(4);
  	printf("reset alarmer: %d \n", ret);
	for (int i; i = 0; i < 15; i++ )
	{
		printf( " sleep % d ... \n ", i );
		sleep( 1 );
	}
	return 0;
}

打印如下:
可以看到,定时信号到时,调用了响应函数sig_handler,并打印出了hello world,然后程序继续执行。
在这里插入图片描述

【参考文章】
1、https://blog.csdn.net/yyyljw/article/details/80741264

Logo

更多推荐