Linux中alarm/setitimer函数(信号函数)

alarm函数

函数原型: unsigned int alarm(unsigned int seconds);

函数描述:设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送 14)SIGALRM信号。进程收到该信号,默认动作终止。每个进程都有且唯一的一个定时器。

函数返回值:返回0或者剩余的秒数,无失败。

复制代码
alarm() returns the number of seconds remaining  until  any  previously
       scheduled alarm was due to be delivered, or zero if there was no previ‐
       ously scheduled alarm.

alarm(5)-----------sleep(2)---------->alarm(5)->接下来还是5秒后产生SIGALRM信号

return 0; return 3(之前的定时器还差3second结束);

取消定时器:alarm(0),返回旧闹钟剩余的秒数

测试:

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <signal.h>
void handler(int signo)
{
	printf("signo==[%d]\n",signo);
}
int main()
{
//给内核注册信号捕捉函数,看看是不是发送SIFGALRM信号
	signal(SIGALRM,handler);

	int n=alarm(10);
	printf("n==[%d]\n",n);
	sleep(2);

	n=alarm(2);//2秒后发送信号
	printf("n==[%d]\n",n);

	sleep(5);//让进程休息5秒,不然进程结束,也收不到信号了
}

运行结果我们也可以发现给进程发出SIGALRM信号时,该进程 直接终止**,并没有sleep(5)那么久才结束 (** 由于 alarm() 函数被 sleep() 函数替代,可能会对定时器造成影响。如果你希望在接收到 SIGALRM 信号后再等待 10 秒钟,可以将 sleep(10) 移到信号处理函数中,并在接收到信号后调用 sleep() 函数。

闹钟实际执行时间=系统时间+用户时间+损耗时间

我们通过测试电脑一秒中能打印多少的数字(printf("%d\n",i++);)可知:

调用printf函数打印数字遇到\n才会打印,打印过程涉及到从用户区到内核区的切换(打印一次切换一次),切换次数越多消耗的时间越长,效率越低,损耗的时间越多。

而我们使用文件重定向操作时(./ arlarm > test.log->写到test.log),由于文件操作带缓冲,所以涉及到用户区到内核区的切换次数大大减少(缓冲区满了才从用户区切换到内核区),从而使损耗大大降低

setitimer函数:

函数原型: int setitimer(int which, const struct itimerval *new_value,

struct itimerval *old_value);

函数作用:设置定时器,可代替alarm函数,精度微秒us,可以实现周期定时。

函数参数:

which:指定定时方式

复制代码
自然定时:ITIMER_REAL(计算自然时间) This  timer counts down in real (i.e., wall clock) time.
                      At each expiration, a SIGALRM(14) signal is generated.

虚拟空间计时(用户空间):ITIMER_VIRTUAL(只计算进程占用cpu的时间) This timer counts down against the  user-mode  CPU  time
                      consumed  by the process.  (The measurement includes CPU
                      time consumed by all threads in the process.)   At  each
                      expiration, a SIGVTALRM signal is generated.

运行时计时(用户+内核)ITIMER_PROF(计算占用cpu及执行系统调用的时间)    This  timer  counts  down  against the total (i.e., both
                      user and system) CPU time consumed by the process.  (The
                      measurement includes CPU time consumed by all threads in
                      the process.)  At each expiration, a SIGPROF  signal  is
                      generated.

                      In  conjunction  with  ITIMER_VIRTUAL, this timer can be
                      used to profile user and system CPU time consumed by the
                      process.

new value:负责设定timeout时间

old_value:存放旧的timeout值,一般设为NULL

复制代码
 struct itimerval {
           struct timeval it_interval;设定以后每几秒执行function(周期)
               struct timeval it_value;设定什么时候执行第一次function
           };

           struct timeval {
               time_t      tv_sec;         秒
               suseconds_t tv_usec;       微秒
           };

测试;

cpp 复制代码
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<unistd.h>
#include <signal.h>
#include <sys/time.h>
void handler(int signo)
{
	printf("signo=[%d]\n",signo);
//alarm(0);可以取消计时器
}
int main()
{
//	signal(SIGALRM,handler);
	//int setitimer(int which, const struct itimerval *new_value,
	//   struct itimerval *old_value);
	struct itimerval value;
//设置间隔
	value.it_interval.tv_sec=1;
	value.it_interval.tv_usec=0;//因为在栈上,不初始化会随机值
//设置第一次发信号的时间
	value.it_value.tv_sec=2;
	value.it_value.tv_usec=0;

	setitimer(ITIMER_REAL,&value,NULL);
//一直执行进程
	while(1)
	{
		sleep(1);
	}

}

结果:2秒之后每隔1秒打印编号:

如果我们不写SIGALRM的信号处理函数,接收到SIGALRM后会直接终止进程(默认行为)。

相关推荐
SelectDB27 分钟前
Apache Doris 在 AgentLogsBench 中领先,支撑 Agent 可观测性生产负载
运维·数据库·agent
荣-1 小时前
从两天到十几分钟:一套 YT Crash 自动化分析工具完整工程复盘
大数据·运维·自动化
酷炫的水壶1 小时前
使用memc-nginx和srcache-nginx模块构建高效透明的缓存机制
运维·nginx·缓存
dddwjzx2 小时前
嵌入式Linux C应用编程入门——信号
linux·嵌入式
范什么特西3 小时前
网络代理问题
java·linux·服务器
姚不倒3 小时前
F5 SSL Profile 证书卸载深入篇
运维·网络协议·负载均衡·ssl·f5
utf8mb4安全女神3 小时前
【Redis数据库】哨兵集群/redis集群/安装配置/主从复制/数据持久化操作/数据结构/安全限制/PHP redis/
linux·服务器·数据结构·数据库·redis·缓存
智商偏低3 小时前
Windows Nginx 完整安装 + 启动教程
运维·nginx
Zk.Sun4 小时前
Linux设置触屏双击距离容差
linux·运维·数据库
Let's Chat Coding4 小时前
对称密钥认证:主机和设备共享同一把密钥
运维·服务器·网络