time

来源:互联网 发布:手机淘宝如何修改差评 编辑:程序博客网 时间:2024/06/05 16:38

I. Linux中与时间相关的函数

  1. 获取当前时间

    • time(2) / time_t (秒) ###精度太低###
    • ftime(3) / struct time (毫秒) ###已被废弃###
    • gettimeofday(2) / struct timeval (微秒) ###满足日常计时的需要,推荐使用###
    • clock_gettime(2) / struct timespec (纳秒) ###精度最高,但是它系统调用的开销大###
  2. 时区转换与日期计算
    转换关系图

  3. 定时操作

    • sleep、alarm、usleep
      实现时有可能用了信号 SIGALRM,在多线程程序中处理信号是个相当麻烦的事情,应当尽量避免.
    • nanosleep、clock_nanosleep
      线程安全的,但是在非阻塞网络编程中,绝对不能用让线程挂起的方式来等待一段时间,程序会失去响应。
    • *itimer、timer_*
      用信号来 deliver 超时,在多线程程序中也会有麻烦。
    • timerfd_*
      把时间变成了一个文件描述符,能很方便地融入到 select/poll 框架中,用统一的方式来处理 IO 事件和超时事件

II. timerfd讲解

  1. 用到的系统时钟:

    • CLOCK_REALTIME:代表机器上可以理解为当前的我们所常看的时间,其当time-of-day 被修改的时候而改变
    • CLOCK_MONOTONIC:代表从过去某个固定的时间点开始的绝对的逝去时间,它不受任何系统time-of-day时钟修改的影响
  2. 涉及的函数:

    • timerfd_create
      @function:生成一个定时器对象;
      @param1: clockid, 填写CLOCK_REALTIME或者CLOCK_MONOTONIC,表示使用哪个时钟来标示定时器的进展;
      @param2: flags, TFD_NONBLOCK(非阻塞,read(fd)如果没有超时发生就直接返回; 默认read(fd)阻塞到超时发生时返回)
      @return: 相应的文件描述符

    • timerfd_settime
      @function:启动和停止定时器;
      @param1: fd, 上个函数返回的文件描述符;
      @param2: flags, 0(相对定时器)或者TFD_TIMER_ABSTIME(绝对定时器)
      @param3: new_value, 指定第一次超时时间和间隔超时时间
      @param4: old_value, 返回此函数调用时定时器的时间设置情况(可以使用timerfd_gettime获取)
      @return: 成功返回0,失败返回-1;

  3. 使用示例

#include <sys/timerfd.h>#include <string.h>#include <time.h>#include <unistd.h>#include <stdlib.h>#include <stdio.h>#include <stdint.h>        /* Definition of uint64_t */#define handle_error(msg) \    do { perror(msg); exit(EXIT_FAILURE); } while (0)static voidprint_elapsed_time(void){    static struct timespec start;    struct timespec curr;    static int first_call = 1;    int secs, nsecs;    if (first_call) {        first_call = 0;        if (clock_gettime(CLOCK_MONOTONIC, &start) == -1)            handle_error("clock_gettime");    }    if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)        handle_error("clock_gettime");    secs = curr.tv_sec - start.tv_sec;    nsecs = curr.tv_nsec - start.tv_nsec;    if (nsecs < 0) {        secs--;        nsecs += 1000000000;    }    printf("%d.%03d: ", secs, (nsecs + 500000) / 1000000);}intmain(int argc, char *argv[]){    struct itimerspec new_value;    int max_exp, fd;    struct timespec now;    struct timespec curr;    uint64_t exp, tot_exp;    ssize_t s;    /* 分别使用不同的时钟创建timerfd */    fd = timerfd_create(CLOCK_MONOTONIC, 0);    //fd = timerfd_create(CLOCK_REALTIME, 0);    if (fd == -1)        handle_error("timerfd_create");#if 0    /* MONOTONIC的绝对定时器 */    if (clock_gettime(CLOCK_MONOTONIC, &curr) == -1)        handle_error("clock_gettime");    new_value.it_value.tv_sec = curr.tv_sec + 3;    new_value.it_value.tv_nsec = curr.tv_nsec;#endif#if 0    /* REALTIME的绝对定时器 */    if (clock_gettime(CLOCK_REALTIME, &now) == -1)        handle_error("clock_gettime");    new_value.it_value.tv_sec = now.tv_sec + 3;    new_value.it_value.tv_nsec = now.tv_nsec;#endif    /* 相对定时器 */    bzero(&new_value, sizeof(new_value));    new_value.it_value.tv_sec = 3;    //if (timerfd_settime(fd, TFD_TIMER_ABSTIME, &new_value, NULL) == -1)    if (timerfd_settime(fd, 0, &new_value, NULL) == -1)        handle_error("timerfd_settime");    print_elapsed_time();    printf("timer started\n");    s = read(fd, &exp, sizeof(uint64_t));    if (s != sizeof(uint64_t))        handle_error("read");    tot_exp += exp;    print_elapsed_time();    printf("read: %llu", (unsigned long long) exp);    exit(EXIT_SUCCESS);}
0 0
原创粉丝点击