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

相关推荐
为java加瓦3 分钟前
Rust 的类型自动解引用:隐藏在人体工学设计中的魔法
java·服务器·rust
罗技12314 分钟前
Docker 启动 Easysearch 时自定义初始密码的几种方式
运维·docker·容器
未来之窗软件服务16 分钟前
操作系统应用开发(二十八)rust OIDC服务器—东方仙盟筑基期
服务器·rustdesk·仙盟创梦ide·东方仙盟
VNDR1 小时前
工欲善其事,必先利其器
linux
维尔切1 小时前
Nginx 反向代理与负载均衡
运维·nginx·负载均衡
心灵宝贝2 小时前
Fedora 38 安装 perl-JSON RPM 包步骤(含依赖问题解决及附安装包)
linux
lilili也2 小时前
Linux——0:安装与配置、命令、gcc
linux
知白守黑2672 小时前
反向代理和负载均衡
运维·负载均衡
杨云龙UP2 小时前
小工具大体验:rlwrap加持下的Oracle/MySQL/SQL Server命令行交互
运维·服务器·数据库·sql·mysql·oracle·sqlserver
阿巴~阿巴~2 小时前
使用 C 语言连接 MySQL 客户端(重点)
服务器·数据库·sql·mysql·ubuntu