1、alarm()函数单次定时(秒位单位):
extern unsigned int alarm(unsigned int __seconds)
每个进程只能有一个闹钟时钟,如果在调用alarm时,以前已为该进程设置过闹钟时钟,而且它还没有超时,则将该闹钟的余留值作为本次alarm函数调用的返回值。以前登记的闹钟时钟则被新值代替。
如果有以前为进程登记的尚未超时的闹钟时钟,而且本次调用的seconds值是0,则取消以前的闹钟时钟,其余留值仍作为alarm函数的返回值。即这样取消之前设置的闹钟:alarm(0)。
alarm超时则产生SIGALRM信号。
2、ualarm()函数循环定时:
ualarm()函数将使当前进程在指定时间(第一个参数,以us位单位)内产生SIGALRM信号,然后每隔指定时间(第2个参数,以us位单位)重复产生SIGALRM信号,如果执行成功,将返回0。
extern __useconds_t ualarm (__useconds_t __value,__useconds_t __interval)
如:ualarm(500000,300000):表示在300000us内产生SIGALRM信号,然后每隔500000us重复产生SIGALRM信号。
ualarm()函数使用示例:
#include
#include
#include
#include
void handler()
{
printf("int:hello\n");
}
int main()
{
int i;
signal(SIGALRM,handler);
printf("%d\n",ualarm(500000,300000));//300000us即0.3s后系统自动产生SIGALRM信号,之后每0.5s产生SIGALRM信号。
whlie(1)
{
sleep(1);
printf("test\n");
}
}
定时器补充知识:
系统为每个进程提供了3个定时器,分别是:
ITIMER_REAL :以系统真实的时间来计算,它送出SIGALRM信号。默认动作:终止
ITIMER_VIRTUAL :以该进程在用户态下花费的时间来计算,它送出SIGVTALRM信号。默认动作:终止
ITIMER_PROF :以该进程在用户态下和内核态下所费的时间来计算。它送出SIGPROF信号。默认动作:终止
setitimer()函数:
setitimer()函数就是用来设置上面那3个定时器的:
int setitimer(int which, const struct itimerval *new_value,struct itimerval *old_value);
参数:
which:哪一个定时器
new_value:设置定时时间和重复的时间间隔,it_interval和it_value的值为0表示禁止对应功能。
old_value:它是用来存储上一次setitimer调用时设置的new_value值,不使用它是可设置为NULL。
其中的结构体:
struct itimerval {
struct timeval it_interval; /* next value */
struct timeval it_value; /* current value */
};
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
setitimer用来设置上面那3个定时器的相关信息,itimerval结构中,it_value指定该定时器产生第一个信号的剩余时间,即多久后产生相应的信号。如果为0,表示禁止该定时器,it_interval用来存储该定时器下一个信号到来的间隔时间。
工作机制是,先对it_value倒计时,当it_value为零时触发信号。然后重置为it_interval。继续对it_value倒计时。一直这样循环下去。假如it_value为0是不会触发信号的,所以要能触发信号,it_value得大于0;假设it_interval为零,仅仅会延时。不会定时(也就是说仅仅会触发一次信号)。基于此机制,setitimer既能够用来延时运行,也可定时运行。
getitimer()函数:
int getitimer(int which, struct itimerval *curr_value);
getitimer()用来获取3个定时器中的某个的相关信息,存储在第二个参数中,存储的是剩余时间,不是设置时的定时时间。
用setitimer()和getitimer()测试ITIMER_REAL定时器:
#include
#include
#include
#include
int main(void)
{
struct itimerval setvalue,value;
setvalue.it_interval.tv_sec=1;
setvalue.it_interval.tv_usec=0;
setvalue.it_value.tv_sec=3;
setvalue.it_value.tv_usec=0;
setitimer(ITIMER_REAL,&setvalue,NULL);
while(1)
{
getitimer(ITIMER_REAL,&value);
printf("ITIMER_REAL:interval:%ds%dms,remain:%ds%dms\n",
value.it_interval.tv_sec,value.it_interval.tv_usec,
value.it_value.tv_sec,value.it_value.tv_usec);
sleep(1);
}
}
运行输出:
book@book-desktop:~/workspace/zongde/chapter10$ ./a.out
ITIMER_REAL:interval:3s0ms,remain:2s999998ms
ITIMER_REAL:interval:3s0ms,remain:1s997688ms
ITIMER_REAL:interval:3s0ms,remain:0s991571ms
Alarm clock
补充知识:进程时间
(原文地址:https://www.cnblogs.com/clover-toeic/p/3845210.html)
进程时间也称CPU时间,用以度量进程使用的中央处理器资源。进程时间以时钟滴嗒计算,通常使用三个进程时间值,即实际时间(Real)、用户CPU时间(User)和系统CPU时间(Sys)。
实际时间指实际流逝的时间;用户时间和系统时间指特定进程使用的CPU时间。
具体区别如下:
Real是从进程开始执行到完成所经历的挂钟(wall clock)时间,包括其他进程使用的时间片(time slice)和本进程耗费在阻塞(如等待I/O操作完成)上的时间。该时间对应秒表(stopwatch)直接测量。
User是进程执行用户态代码(内核外)耗费的CPU时间,仅统计该进程执行时实际使用的CPU时间,而不计入其他进程使用的时间片和本进程阻塞的时间。
Sys是该进程在内核态运行所耗费的CPU时间,即内核执行系统调用所使用的CPU时间。
CPU总时间(User+Sys)是CPU执行用户进程操作和内核(代表用户进程执行)系统调用所耗时间的总和,即该进程(包括其线程和子进程)所使用的实际CPU时间。若程序循环遍历数组,则增加用户CPU时间;若程序执行exec或fork等系统调用,则增加系统CPU时间。
在多核处理器机器上,若进程含有多个线程或通过fork调用创建子进程,则实际时间可能小于CPU总时间——因为不同线程或进程可并行执行,但其时间会计入主进程的CPU总时间。若程序在某段时间处于等待状态而并未执行,则实际时间可能大于CPU总时间。其数值关系总结如下:
●Real < CPU,表明进程为计算密集型(CPU bound),利用多核处理器的并行执行优势;
●Real ≈ CPU,表明进程为计算密集型(CPU bound),未并行执行;
●Real > CPU,表明进程为I/O密集型(I/O bound),多核并行执行优势并不明显。
在单核处理器上,Real时间和CPU时间之差,即Real- (User + Sys)是所有延迟程序执行的因素的总和。可估算程序运行期间的CPU利用率为CpuUsage = (User + Sys)/ Real * 100(%)。
在SMP(对称多处理系统)上,该差值近似为Real* ProcessorNum - (User + Sys)。这些因素包括:
●调入程序文本和数据的I/O操作;
●获取程序实际使用内存的I/O操作;
●由其它程序消耗的CPU用时;
●由操作系统消耗的CPU用时。