alarm函数
函数原型: unsigned int alarm(unsigned int seconds);
函数描述:设置定时器(闹钟)。在指定seconds后,内核会给当前进程发送 14)SIGALRM信号。进程收到该信号,默认动作终止。每个进程都有且唯一的一个定时器。
函数返回值:返回0或者剩余的秒数,无失败。
alarm() returns the number of seconds remaining until any previouslyscheduled 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),返回旧闹钟剩余的秒数
测试:
#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)那么久才结束
因为sleep()和阻塞时遇到信号会中断,并产生EINTR错误
闹钟实际执行时间=系统时间+用户时间+损耗时间
我们通过测试电脑一秒中能打印多少的数字(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 timeconsumed by the process. (The measurement includes CPUtime consumed by all threads in the process.) At eachexpiration, a SIGVTALRM signal is generated.运行时计时(用户+内核)ITIMER_PROF(计算占用cpu及执行系统调用的时间) This timer counts down against the total (i.e., bothuser and system) CPU time consumed by the process. (Themeasurement includes CPU time consumed by all threads inthe process.) At each expiration, a SIGPROF signal isgenerated.In conjunction with ITIMER_VIRTUAL, this timer can beused to profile user and system CPU time consumed by theprocess.
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; 微秒};
测试;
#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后会直接终止进程(默认行为)。