12_Linux时间处理操作

时间类常用结构体

time_t 秒级

time_t 是一个整数类型,用于表示从 Unix 纪元(1970 年 1 月 1 日 00:00:00 UTC)开始的秒数。它是时间戳的标准表示形式。

time_t rawtime;
time(&rawtime);  // 获取当前时间的时间戳

struct timespec 秒级和纳秒级结构体

struct timespec 用于表示高精度的时间,包括秒和纳秒。

struct timespec {
    time_t tv_sec;   // 秒
    long tv_nsec;    // 纳秒
};

struct timespec ts;
clock_gettime(CLOCK_REALTIME, &ts);  // 获取当前时间

struct timeval 秒级和微秒级结构体

struct timeval 用于表示微秒级的时间,常用于计时和超时操作。

struct timeval {
    time_t tv_sec;   // 秒
    suseconds_t tv_usec;  // 微秒
};

struct timeval tv;
gettimeofday(&tv, NULL);  // 获取当前时间

struct tm 转换分解后的时间结构体

struct tm 代表一个分解的时间结构体,包含了年、月、日、小时、分钟、秒等各个组成部分。通常通过 localtime 或 gmtime 从 time_t 类型的时间戳转换而来。

#include <time.h>

struct tm {
    int tm_sec;  // 秒 [0, 60]
    int tm_min;  // 分钟 [0, 59]
    int tm_hour; // 小时 [0, 23]
    int tm_mday; // 月份中的天数 [1, 31]
    int tm_mon;  // 月份 [0, 11]
    int tm_year; // 自 1900 年以来的年数
    int tm_wday; // 星期几 [0, 6] (周日为 0)
    int tm_yday; // 一年中的第几天 [0, 365]
    int tm_isdst; // 夏令时标志
};

struct tm * timeinfo;
time_t rawtime;

time(&rawtime);
timeinfo = localtime(&rawtime);  // 转换为本地时间

struct itimerspec 定时器的结构体值

struct itimerspec 用于表示定时器的值,包括定时器的到期时间和周期。

struct itimerspec {
    struct timespec it_interval;  // 定时器重复触发的时间间隔
    struct timespec it_value;     // 定时器首次触发前等待的时间
};


struct itimerspec timer;
// 设置定时器
timer.it_value.tv_sec = 5;  // 定时器首次触发前等待的时间
timer.it_value.tv_nsec = 0; // 纳秒部分
timer.it_interval.tv_sec = 1;  // 定时器重复触发的时间间隔
timer.it_interval.tv_nsec = 0; // 纳秒部分

示例:使用select监听定时文件描述符是否到达时间

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/timerfd.h>
#include <time.h>
#include <string.h>
#include <inttypes.h>
#include <sys/select.h>

int main() {
    int timerfd;
    struct itimerspec timer;
    char buf[8];  // 事件通知的大小为 8 字节
    uint64_t count;  // 存储读取的计数值

    // 创建定时器文件描述符
    timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK | TFD_CLOEXEC);
    if (timerfd == -1) {
        perror("timerfd_create");
        exit(EXIT_FAILURE);
    }

    // 设置定时器首次触发前等待的时间(it_value)和重复触发的时间间隔(it_interval)
    timer.it_value.tv_sec = 5;  // 定时器首次触发前等待 5 秒
    timer.it_value.tv_nsec = 0; // 纳秒部分
    timer.it_interval.tv_sec = 3;  // 定时器重复触发的时间间隔为 1 秒
    timer.it_interval.tv_nsec = 0; // 纳秒部分

    if (timerfd_settime(timerfd, 0, &timer, NULL) == -1) {
        perror("timerfd_settime");
        close(timerfd);
        exit(EXIT_FAILURE);
    }

    fd_set fds;
    struct timeval timeout;

    // 监听定时器事件
    while (1) {
        FD_ZERO(&fds);
        FD_SET(timerfd, &fds);

        timeout.tv_sec = 1;  // 超时时间为 1 秒
        timeout.tv_usec = 0;

        if (select(timerfd + 1, &fds, NULL, NULL, &timeout) == -1) {
            perror("select");
            close(timerfd);
            exit(EXIT_FAILURE);
        }

        if (FD_ISSET(timerfd, &fds)) {
            ssize_t n = read(timerfd, buf, sizeof(buf));
            if (n != sizeof(buf)) {
                perror("read");
                close(timerfd);
                exit(EXIT_FAILURE);
            }
            memcpy(&count, buf, sizeof(count));
            printf("Timer expired, count: %" PRIu64 "\n", count);
        }
    }

    close(timerfd);
    return 0;
}

localtime获取的数据存储问题

localtime获得的时间数据存储在栈上的固定位置,每次调用该函数,都会更新该值,为了防止出错,需要拷贝出来,示例:

#include <string.h>
#include <inttypes.h>
#include <sys/select.h>

int main() {
    time_t time_now;
    struct tm* tm;

    time(&time_now);
    tm = localtime(&time_now);

    printf("第一次:%d-%d-%d %d:%d:%d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

    sleep(10);

    time(&time_now);
    localtime(&time_now);
    printf("第二次:%d-%d-%d %d:%d:%d\n", tm->tm_year, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);

    return 0;
}

结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月光在发光

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值