gettimeofday函数如何精确获取当前时间?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 C语言 正文

这是一个非常经典且在 Linux/Unix 系统中广泛使用的函数,用于获取当前时间,虽然在新代码中推荐使用更现代的 clock_gettime,但 gettimeofday 因其简单性和广泛的历史存在,仍然非常重要。

c语言 gettimeofday
(图片来源网络,侵删)

函数原型

gettimeofday 函数定义在 <sys/time.h> 头文件中。

#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);

功能描述

gettimeofday 函数用于获取当前日历时间(精确到微秒),它将时间信息存储在 struct timeval 结构体中。

参数详解

函数有两个参数:

a) struct timeval *tv (输入/输出参数)

这是一个指向 timeval 结构体的指针,函数会将获取到的时间信息填充到这个结构体中,如果这个参数是 NULL,则函数不会获取或填充时间信息。

c语言 gettimeofday
(图片来源网络,侵删)

timeval 结构体的定义如下:

struct timeval {
    time_t      tv_sec;     // 秒 (seconds since Jan. 1, 1970)
    suseconds_t tv_usec;    // 微秒 (microseconds, 0 to 999,999)
};
  • tv_sec: 自 Unix 纪元(1970年1月1日00:00:00 UTC)以来经过的秒数。
  • tv_usec: 在当前秒内经过的微秒数(0 到 999,999)。

b) struct timezone *tz (输入/输出参数)

这是一个指向 timezone 结构体的指针,用于获取时区信息,在现代系统中,这个参数几乎总是被忽略,为了可移植性和避免问题,强烈建议将其设置为 NULL

timezone 结构体的定义如下(在 <sys/time.h> 中):

struct timezone {
    int tz_minuteswest; // 格林威治时间以西的分钟数
    int tz_dsttime;     // 夏令时类型
};

返回值

  • 成功时:返回 0
  • 失败时:返回 -1,并设置 errno 来指示错误原因(EFAULT 表示无效的指针地址)。

使用示例

下面是一个完整的示例,展示如何使用 gettimeofday 获取当前时间并将其打印出来。

c语言 gettimeofday
(图片来源网络,侵删)
#include <stdio.h>
#include <sys/time.h> // 包含 gettimeofday 的头文件
#include <unistd.h>   // 包含 sleep 函数的头文件
int main() {
    struct timeval start_time, end_time;
    // 获取开始时间
    if (gettimeofday(&start_time, NULL) != 0) {
        perror("gettimeofday (start) failed");
        return 1;
    }
    printf("程序开始运行...\n");
    printf("开始时间: 秒 = %ld, 微秒 = %ld\n", start_time.tv_sec, start_time.tv_usec);
    // 模拟一些工作,比如休眠1秒
    sleep(1);
    // 获取结束时间
    if (gettimeofday(&end_time, NULL) != 0) {
        perror("gettimeofday (end) failed");
        return 1;
    }
    printf("程序结束运行...\n");
    printf("结束时间: 秒 = %ld, 微秒 = %ld\n", end_time.tv_sec, end_time.tv_usec);
    // 计算耗时
    long seconds = end_time.tv_sec - start_time.tv_sec;
    long microseconds = end_time.tv_usec - start_time.tv_usec;
    // 处理微秒借位
    if (microseconds < 0) {
        seconds--;
        microseconds += 1000000;
    }
    double elapsed_time = seconds + microseconds / 1000000.0;
    printf("程序总耗时: %ld 秒 %ld 微秒\n", seconds, microseconds);
    printf("程序总耗时 (秒): %.6f\n", elapsed_time);
    return 0;
}

编译和运行

在 Linux 或 macOS 系统上,使用 GCC 编译:

gcc -o time_example time_example.c
./time_example

预期输出

程序开始运行...
开始时间: 秒 = 1678886400, 微秒 = 123456
程序结束运行...
结束时间: 秒 = 1678886401, 微秒 = 125345
程序总耗时: 1 秒 1889 微秒
程序总耗时 (秒): 1.001889

(注意:秒数和微秒数会根据你运行程序的时间而变化)


gettimeofday vs. clock_gettime

虽然 gettimeofday 很好用,但它并不是 POSIX 标准的一部分,而是 BSD 和 Linux 的特定扩展,更重要的是,它已经被标记为过时

现代 C 编程中,推荐使用 clock_gettime

clock_gettime 的优势

  1. POSIX 标准clock_gettime 是 POSIX.1-2001 标准的一部分,具有更好的可移植性(适用于 Linux, macOS, 以及其他遵循 POSIX 的系统)。
  2. 更高的精度clock_gettime 可以提供纳秒级的精度(如果系统支持),而 gettimeofday 通常是微秒级。
  3. 更多的时间源clock_gettime 允许你选择不同类型的时钟源,而不仅仅是日历时间。
    • CLOCK_REALTIME: 类似于 gettimeofday,返回系统范围的实时时间。
    • CLOCK_MONOTONIC: 返回一个单调递增的时钟,它不受系统时间调整(如 NTP 同步或用户手动修改时间)的影响。非常适合用于测量耗时
    • CLOCK_PROCESS_CPUTIME_ID: 测量当前进程消耗的 CPU 时间。
    • CLOCK_THREAD_CPUTIME_ID: 测量当前线程消耗的 CPU 时间。

clock_gettime 示例

下面是使用 clock_gettime 重新实现上面的耗时计算示例:

#define _POSIX_C_SOURCE 199309L // 需要定义这个宏才能使用 clock_gettime
#include <stdio.h>
#include <time.h>      // 包含 clock_gettime 的头文件
#include <unistd.h>    // 包含 sleep 函数的头文件
int main() {
    struct timespec start_time, end_time;
    // 使用 CLOCK_MONOTONIC 来测量耗时,因为它不受系统时间变化的影响
    if (clock_gettime(CLOCK_MONOTONIC, &start_time) != 0) {
        perror("clock_gettime (start) failed");
        return 1;
    }
    printf("程序开始运行...\n");
    printf("开始时间: 秒 = %ld, 纳秒 = %ld\n", start_time.tv_sec, start_time.tv_nsec);
    sleep(1);
    if (clock_gettime(CLOCK_MONOTONIC, &end_time) != 0) {
        perror("clock_gettime (end) failed");
        return 1;
    }
    printf("程序结束运行...\n");
    printf("结束时间: 秒 = %ld, 纳秒 = %ld\n", end_time.tv_sec, end_time.tv_nsec);
    // 计算耗时
    long seconds = end_time.tv_sec - start_time.tv_sec;
    long nanoseconds = end_time.tv_nsec - start_time.tv_nsec;
    // 处理纳秒借位
    if (nanoseconds < 0) {
        seconds--;
        nanoseconds += 1000000000;
    }
    double elapsed_time = seconds + nanoseconds / 1000000000.0;
    printf("程序总耗时: %ld 秒 %ld 纳秒\n", seconds, nanoseconds);
    printf("程序总耗时 (秒): %.9f\n", elapsed_time);
    return 0;
}

特性 gettimeofday clock_gettime
头文件 <sys/time.h> <time.h>
标准 BSD/Linux 扩展,非 POSIX POSIX.1-2001 及以后
状态 过时 推荐
精度 微秒 (µs) 纳秒 (ns,如果支持)
时间源 只有日历时间 (CLOCK_REALTIME 类似) 多种时钟源 (REALTIME, MONOTONIC, PROCESS_CPUTIME, 等)
可移植性 较差 (主要在 Unix-like 系统) 更好 (POSIX 标准)
  • 对于新项目,请优先使用 clock_gettime,它更标准、更灵活、精度更高。
  • 维护旧代码或进行简单的、跨平台要求不高的快速原型开发时,gettimeofday 仍然是一个简单有效的选择。
  • 绝对不要gettimeofday 来测量耗时,因为它会受到系统时间同步的影响,应该使用 clock_gettime(CLOCK_MONOTONIC, ...) 来测量时间间隔。
-- 展开阅读全文 --
头像
织梦文件管理为何没有dede文件?
« 上一篇 2025-12-21
织梦dede5.7后台如何优化?
下一篇 » 2025-12-21

相关文章

取消
微信二维码
支付宝二维码

目录[+]