本文函数列表:
获取当前时间(距离1970年)
gettimeofday(2)
获取当前时间(实际字符串)
localtime(3)
asctime(3)
time(2)
setitimer实现定时器
getitimer(2)
setitimer(2)
一、获取当前时间(距离1970年)
struct timeval {
long tv_sec; //秒
long tv_usec; //微妙
};
struct timezone {
int tz_minuteswest; //和Greenwich时间差了多少分钟
int tz_dsttime; //日光节约时间的状态
};
gettimeofday(2)
#include <sys/time.h>
#include <unistd.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
功能: 取得当前时间
参数:
tv:回传参数,当前时间
tz:回传参数,当地时区信息
返回值:
成功 0
错误 -1 errno被设置
例:
#include <sys/time.h>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
gettimeofday(&tv1, &tz);
/*do something*/
gettimeofday(&tv2, &tz);
t = tv2.tv_sec - tv1.tv_sec + (tv2.tv_usec - tv1.tv_usec) * pow(10, -6); //单位:秒
//pow(10, -6) ------10的-6次方
二、获取当前时间(实际字符串)
localtime(3)
头文件:#include <time.h>
功能: localtime把从1970-1-1零点零分到当前时间系统所偏移的秒数时间转换为本地时间,此函数获得的tm结构体的时间是日历时间。
struct tm *localtime(const time_t *timep);
参数:
timep:从1970年到现在的时间差,可以使用time(2)函数获取。
返回值:
返回指向tm 结构体的指针,tm结构体是time.h中定义的用于分别存储时间的各个量(年月日等)的结构体。
asctime(3)
头文件:#include <time.h>
功能: asctime把struct tm结构体保存的时间信息转换为字符串形式
char *asctime(const struct tm *tm);
参数:
tm:struct tm结构体,表示时间
返回值:
返回tm结构体指示的时间的字符串格式,字符串中自带’\n’
time(2)
头文件:#include <time.h>
功能: 获得1970年到现在经过了的时间
time_t time(time_t *tloc);
参数:
tloc:NULL即可;如果非NULL,则返回值也会存在tloc指向的内存中。
返回值:
获得1970年到现在经过了的时间,保存在struct tm结构体里
注: struct tm结构体
struct tm {
int tm_sec; /* Seconds (0-60) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23) */
int tm_mday; /* Day of the month (1-31) */
int tm_mon; /* Month (0-11) */
int tm_year; /* Year - 1900 ,从1900到现在的年数*/
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
int tm_isdst; /* Daylight saving time */
};
例:
1 #include <stdio.h>
2 #include <stddef.h>
3 #include <time.h>
4 int main(void)
5 {
6 time_t timer;//time_t就是long int 类型
7 struct tm *tblock;
8 timer = time(NULL);
9 tblock = localtime(&timer);
10 printf("Local time is: %s", asctime(tblock));
11 return 0;
12 }
三、Linux时间和定时器介绍
运行一个进程的时候,进程所消耗的时间包括三个部分:
用户时间:进程消耗在用户态的时间。也叫用户CPU时间;
内核时间:进程消耗在内核态的时间。也叫系统CPU时间;
睡眠时间:进程消耗在等待I/O,睡眠等不被调度的情况下的时间。
墙上时钟时间(wall clock time):等于用户时间+内核时间+睡眠时间
CPU时间:用户时间+内核时间
内核为每个进程维护三个计时器
真实计时器:统计进程的执行时间(墙上时间)
执行时间=用户时间+内核时间+睡眠时间
虚拟计时器:统计进程的用户时间
实用计时器:统计进程的用户时间和内核时间之和
这三个计时器除了统计进程的各种时间外,还可以按照各自的计时规则,以定时器的方式工作,向进程周期性的发送不同信号。
SIGALRM 真实定时器
SIGVTALRM 虚拟定时器
SIGPROF 实用定时器
四、setitimer实现定时器
通过使用setitimer(2)设置、启动、关闭定时器,
使用getitimer(2)
getitimer(2)
#include <sys/time.h>
int getitimer(int which, struct itimerval *curr_value);
功能: 获取当前进程的计时器的当前值
参数:
which:
ITIMER_REAL:真实计时器
ITIMER_VIRTUAL:虚拟计时器
ITIMER_PROF:实用计时器
curr_value:回传参数,计时器当前值
返回值:
成功 0
错误 -1 errno被设置
setitimer(2)
#include <sys/time.h>
int setitimer(int which, const struct itimerval *new_value,
struct itimerval *old_value);
功能: 设置定时器,it_value会逐渐递减,当递减到0时会被重新设置为it_interval,然后继续递减,因此it_value是第一次触发定时器的时间,it_interval是后续固定的触发时间间隔。
示例:
设置it_value为5秒,it_interval为1秒,则定时器开始工作后,5秒后发送一次相应的定时器信号,之后每1秒发送一次相应的信号。
类似于手机上设置闹钟,设置早晨9点响铃,达到早晨9点后则响铃,第一次响铃后每隔10分钟继续响铃,直到你点击不再响铃。
参数:
which:
ITIMER_REAL:真实定时器
ITIMER_VIRTUAL:虚拟定时器
ITIMER_PROF:实用定时器
new_value:定时器新值
old_value:定时器原来的值
返回值:
成功 0
错误 -1 errno被设置
补充:
struct itimerval{
/*固定的间隔时间*/
struct timeval it_interval;/*next value*/
/*第一次定时器触发间隔时间*/
struct timeval it_value;/*current value*/
};
struct timeval{
long tv_sec; /*seconds*/
long tv_usec; /**microseconds/
};
例:sleep函数实现原理
例:实现类似定时器中断函数
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/time.h>
void doit(int sig){
printf("alrm\n");
return ;
}
int main(void){
struct itimerval new;
new.it_value.tv_sec=5;
new.it_value.tv_usec=0;
new.it_interval.tv_sec=0;
new.it_interval.tv_usec=500000;
signal(SIGALRM,doit);
setitimer(ITIMER_REAL,&new,NULL);
while(1);
return 0;
}
结果:
下方输出结果中第一个alrm是5秒后输出的,剩下的alrm都是间隔0.5输出一次
am@am-PC:test$ ./a.out
alrm
alrm
alrm
alrm
alrm
alrm
alrm
alrm