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后会直接终止进程(默认行为)。

相关推荐
搬码临时工2 小时前
电脑同时连接内网和外网的方法,附外网连接局域网的操作设置
运维·服务器·网络
藥瓿亭2 小时前
K8S认证|CKS题库+答案| 3. 默认网络策略
运维·ubuntu·docker·云原生·容器·kubernetes·cks
Gaoithe2 小时前
ubuntu 端口复用
linux·运维·ubuntu
德先生&赛先生3 小时前
Linux编程:1、文件编程
linux
程序猿小D3 小时前
第16节 Node.js 文件系统
linux·服务器·前端·node.js·编辑器·vim
gsls2008084 小时前
ocrapi服务docker镜像使用
运维·docker·容器
多多*4 小时前
微服务网关SpringCloudGateway+SaToken鉴权
linux·开发语言·redis·python·sql·log4j·bootstrap
文牧之4 小时前
PostgreSQL 的扩展pg_freespacemap
运维·数据库·postgresql
AWS官方合作商5 小时前
基于AWS Serverless架构:零运维构建自动化SEO内容生成系统
运维·serverless·aws
whp4045 小时前
windows server2019 不成功的部署docker经历
运维·docker·容器