apue学习之使用setitimer实现alarm函数
1 alarm函数
#include<unistd.h>
unsigned int alarm(unsigned int seconds);
//返回值:0或以前设置的闹钟时间的余留秒数
参数seconds是需要设置的时钟秒数,当时间到达后,内核会产生SIGALRM信号,如果不捕捉或忽略这个信号,系统默认动作是终止调用该alarm函数的进程。
每个进程只能有一个闹钟时间。如果在调用alarm时,之前该进程已经调用过alarm函数且还没有超时,那么返回上次设置闹钟的剩余时间,如果之前没有调用过alarm,那么返回0。
1.1 alarm函数的实例
// File Name: alarm_test.c
// Author: AlexanderGan
// Created Time: Fri 19 Jun 2020 09:34:03 AM CST
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
int main(int argc, char* argv[]){
int num = 1;
alarm(5);
while(1)
{
printf("time %d s\n",num++);
sleep(1);
}
return 0 ;
}
1.2 执行情况
2 setitimer系统调用函数
#include<sys/time.h>
int setitimer(int which, const struct itimerval *new value, struct itimerval *old value);
struct itimerval{
struct timeval it_interval;//周期时间
struct timeval it_value;//下一次闹钟的时间
}
struct timeval{
time_t tv_sec;//秒s
suseconds_t tv_usec;//微秒us
}
//参数:which:指定定时方式
//自然定时:ITIMER_REAL → 14)SIGALRM 计算自然时间
//虚拟空间计时(用户空间):ITIMER_VIRTUAL → 26)SIGVTALRM 只计算进程占用cpu的时间
//运行时计时(用户+内核):ITIMER_PROF → 27)SIGPROF 计算占用cpu及执行系统调用的时间
//返回值:成功:0;失败:-1,并设置errno
2.1 setitimer的实例
// File Name: alarm_test.c
// Author: AlexanderGan
// Created Time: Fri 19 Jun 2020 09:34:03 AM CST
#include<stdio.h>
#include<signal.h>
#include<stdlib.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<unistd.h>
#include<fcntl.h>
#include<sys/time.h>
void sig_handler(int sig){
if(sig == SIGALRM)//SIGALRM的信号编号为14
{
printf("the SIGALRM id is : %d \n",sig);
}
}
int main(int argc, char* argv[]){
int num = 1;
struct itimerval newit = {{5,0},{2,0}};//第一次超时是2s,之后都是5s
//函数名传参相当于函数指针;要在信号产生函数之前设置信号获取函数signal
signal(SIGALRM,sig_handler);
setitimer(ITIMER_REAL,&newit,NULL);
while(1)
{
printf("time %d s\n",num++);
sleep(1);
}
return 0 ;
}
2.2 执行情况
3 仿alarm函数的实现
unsigned int i_alarm(unsigned int seconds)
{
struct itimerval oldit, newit = {{0,0},{0,0}};
newit.it_value.tv_sec = seconds;//将时间赋值给新时钟
//系统调用将会查询上个闹钟的剩余时间,并写到oldit中(每个进程只有1个闹钟时间)
setitimer(ITIMER_REAL,&newit,&oldit);
return oldit.it_value.tv_sec;//返回上个时钟剩余秒数
}
这个函数使用起来的效果类似于alarm,略过。