Linux time时间概述

来源:互联网 发布:辐射4捏脸数据 美女 编辑:程序博客网 时间:2024/06/05 20:35

(一)前言

说起time,一般有两种,一个是计时,一个是定时.

最近学APUE看到时间和日期这部分,想起muduo书中的实现规则:

1.计时使用gettimeofday(2)来获取当前时间

原因在于比time有更好的精度,比clock_gettime有更小的开销

2.定时使用timerfd_*系列函数来处理定时任务

原因在于可以拿到一个fd放到Reactor中统一管理,并且不像sleep那样产生异步信号,
书中提到可以个用epoll/poll等的timeout参数来指定超时时间,从而实现定时任务,当时并不知道实现原理,
前段时间看Libevent的Timer实现就明白了,在Libevent中,维护一个时间的小根堆,来管理多个超时事件

这又让我想起更早些的一次面试,当时问如何管理定时事件,我说道timerfd,不过面试官好像并不知道这个timerfd的存在,然后把epoll timeout解释给我..

(二)常用时间类型

time_t
struct tm
struct timeval
struct timespec

1.1 time_t

time_t实际是一个长整型:

// time.c#include <time.h>#include <stdio.h>int main(){    time_t t;    return 0;}

终端输入:
gcc -E time.c | grep __time_t
查看结果:

typedef long int __time_t;typedef __time_t time_t;

time_t实际是一个长整型。其值表示为从UTC(coordinated universal time)时间1970年1月1日00时00分00秒(也称为Linux系统的Epoch时间)到当前时刻的秒数。

#include <time.h>time_t time(time_t *calptr);//将返回当前的时间

1.2 struct tm

struct tm {    int tm_sec;         /* seconds */    int tm_min;         /* minutes */    int tm_hour;        /* hours */    int tm_mday;        /* day of the month */    int tm_mon;         /* month */    int tm_year;        /* year */    int tm_wday;        /* day of the week */    int tm_yday;        /* day in the year */    int tm_isdst;       /* daylight saving time */};

localtimegmtime将日历时间转换成分解的时间,存放在struct tm

#include <time.h>struct tm*gmtime(const time_t *calptr);struct tm*localtime(const time_t *calptr);

gmtime返回格林时间、localtime会返回本地时间,例如返回北京时间

有意思的事情是,time得到是从1970年开始经过的秒数,不过这个结构体中的成员是从1900年算起

只得到这个结构体是无法知道当前确切的时间,通过char *asctime(const struct tm *tm);可以将这个结构体可视化出来:

#include <time.h>#include <stdio.h>int main(){    time_t t;    time(&t);    printf("%ld\r\n",t);    struct tm* tt=gmtime(&t);//格林时间    struct tm* localtt=localtime(&t);//北京时间    printf("gm time: %s\r\n",asctime(tt));    printf("local time: %s\r\n",asctime(localtt));    printf("sec: %d\r\n",tt->tm_sec);    printf("min: %d\r\n",tt->tm_min);    printf("hour: %d\r\n",tt->tm_hour);    printf("mday: %d\r\n",tt->tm_mday);    printf("mon: %d\r\n",tt->tm_mon);    printf("year: %d\r\n",tt->tm_year);    printf("wday: %d\r\n",tt->tm_wday);    printf("yday: %d\r\n",tt->tm_yday);    return 0;}

asctime(localtime(&t))的效果就相当于ctime(&t)

1.3 struct timeval

对应的函数是gettimeofday,APUE上说SUSv4指定该函数已经放弃使用,不过我依稀记得我本科毕业设计用它来计算程序运行的时间。
gettimeofday的优势在于可以返回更高的精度(可到微秒级),封装在结构体中:

struct timeval {    time_t      tv_sec;     /* seconds */    suseconds_t tv_usec;    /* microseconds */};

1.4 struct timespec

对应函数

#include <sys/time.h>int clock_gettime(clockid_t clock_id, struct timespec *tsp);

当ID设置为CLOCK_REALTIME时,clock_gettime将提供与time函数相似的功能,不过在系统支持高精度时间值的情况下,该函数提供纳米级别精度。

struct timespec {    time_t   tv_sec;        /* seconds */        long     tv_nsec;       /* nanoseconds */};

(三)系统调用

上文中提到的系统调用有time()、ctime()、gmtime()、localtime()、asctime()、gettimeofday()

除此之外,用strftmie可以格式化时间输出:

#include <stdio.h>#include <stdlib.h>#include <time.h>intmain(void){    time_t t;    struct tm *tmp;    char buf1[16];    char buf2[64];    time(&t);    tmp = localtime(&t);    if (strftime(buf1, 16, "time and date: %r, %a %b %d, %Y", tmp) == 0)        printf("buffer length 16 is too small\n");    else        printf("%s\n", buf1);    if (strftime(buf2, 64, "time and date: %r, %a %b %d, %Y", tmp) == 0)        printf("buffer length 64 is too small\n");    else        printf("%s\n", buf2);    exit(0);}

(四)参考

1.apue
2.http://blog.csdn.net/water_cow/article/details/7521567#
3.linux多线程编程(陈硕)

1 0