当前位置: 首页 > news >正文

Linux的时间函数

ucos中有systick这个系统时间滴答,那linux中有没有这种系统时间滴答呢?有,jiffies,但是用户空间不可以使用。那么在linux中除了使用timer定时器进行定时,可以通过时间滴答的方式来进行粗略的计时吗?下面介绍一下几个linux中使用的时间函数。

一、clock_gettime()

#include <time.h>int clock_gettime(clockid_t clk_id, struct timespec *tp);
  • clk_id:指定要获取的时钟类型。

  • tp:指向 timespec 结构体的指针,用于存储当前时间。

第一个参数是一个时钟类型标识符

时钟类型描述是否受系统时间更改
CLOCK_REALTIME实时时钟(系统当前时间)
CLOCK_MONOTONIC单调时钟(启动后递增)不会

 其中CLOCK_MONOTONIC表示:

从某个固定时间点(通常是系统启动时间)开始递增的时间,不受系统时间修改的影响

它的主要特性是:

  • 单调递增,不会因为用户或NTP调整系统时间而倒退或跳变。

  • 非常适合做 计时超时判断事件间隔测量

第二个参数:

struct timespec {time_t   tv_sec;   // 秒long     tv_nsec;  // 纳秒(0 ~ 999999999)
};

示例:超时判断,毫秒级

#include <stdio.h>
#include <time.h>
#include <unistd.h>long get_current_time_ms() {struct timespec ts;clock_gettime(CLOCK_MONOTONIC, &ts);  // 不受系统时间调整影响return ts.tv_sec * 1000 + ts.tv_nsec / 1000000;
}int main() {long timeout_ms = 3000;  // 设置超时时间为3000mslong start_time = get_current_time_ms();printf("开始等待...\n");while (1) {long now = get_current_time_ms();if ((now - start_time) >= timeout_ms) {printf("超时发生:已等待 %ld ms\n", now - start_time);break;}// 模拟处理usleep(100 * 1000);  // 睡眠100ms}return 0;
}

二、gettimeofday

#include <sys/time.h>int gettimeofday(struct timeval *tv, struct timezone *tz);
  • tv: 用于存储当前时间(秒+微秒)

  • tz: 通常设置为 NULL(时区参数已弃用)

struct timeval {time_t      tv_sec;     // 秒(从1970-01-01 00:00:00 UTC 到现在的秒数)suseconds_t tv_usec;    // 微秒(0 ~ 999999)
};

这个函数与clock_gettime函数的CLOCK_REALTIME类似,不过gettimeofday的精度是微秒,clock_gettime的精度是纳秒。

适用于:时间戳记录、事件间隔计算、日志时间打点

三、Time

#include <time.h>time_t time(time_t *t);
  • 返回自 1970年1月1日 00:00:00 UTC 起经过的 秒数

  • 参数 t

    • 如果不为 NULL,会把结果存入 *t 中。

    • 如果是 NULL,就只返回当前时间戳。

示例:

#include <stdio.h>
#include <time.h>int main() {time_t now = time(NULL);printf("当前时间:%s", ctime(&now));  // ctime 会返回格式化字符串return 0;
}当前时间:Thu Apr 25 10:40:31 2025

四、mktime(UTC0)

mktime() 是一个非常实用的 C 标准库函数,用于将一个 结构化时间(struct tm)转换为时间戳(time_t,即自 1970-01-01 00:00:00 UTC 起的秒数。UTC0

#include <time.h>time_t mktime(struct tm *timeptr);
  • 参数:timeptr 是一个指向 struct tm 的指针,表示你构造的本地时间。

  • 返回值:转换后的时间戳(time_t 类型)。

    • 如果无法转换(比如时间不合法),返回 -1

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, 注意 0 是 1 月)int tm_year;   // 年份从 1900 开始计算 (即2025年是125)int tm_wday;   // 星期几 (0-6, 0是星期日) —— mktime 会帮你填充int tm_yday;   // 年内第几天 (0-365) —— mktime 会填充int tm_isdst;  // 夏令时标志,0表示不开启,>0表示启用,<0表示自动判断
};

示例:

#include <stdio.h>
#include <time.h>int main() {struct tm t = {0};t.tm_year = 2025 - 1900;  // 年份从1900算起t.tm_mon  = 3;            // 4月(注意:从0算起)t.tm_mday = 25;t.tm_hour = 10;t.tm_min  = 30;t.tm_sec  = 0;time_t ts = mktime(&t);if (ts == -1) {printf("时间转换失败\n");} else {printf("时间戳:%ld\n", ts);printf("本地时间字符串:%s", ctime(&ts));}return 0;
}
  • 构造一个未来/过去的时间戳

  • difftime() 配合使用计算时间差。

  • 构建“闹钟时间”、“超时时间”等目标时间点。

四、timegm

time_t timegm(struct tm *tm);

此函数与mktime的区别就是,传给mktime的时间会根据系统所在的地区减去对应的时区值。比如传2025.4.25.14.00返回值实际是2025.4.25.6.00的UTC时间戳。

而timegm的返回值是传入什么就返回什么,是对应的。比如传2025.4.25.14.00返回值实际就是2025.4.25.14.00的UTC时间戳。

  • mktime() 会把它当作本地时间转换为时间戳,会加入系统时区偏移;

  • timegm() 会严格按照它就是 UTC 时间,不做时区偏移处理

五、localtime(受当前系统时区影响或者说本身处理时区)

主要用于将 UTC 时间戳(time_t)转换成本地时间(struct tm 结构体)。受时区影响

#include <time.h>struct tm *localtime(const time_t *timep);
  • timep:一个指向 time_t 类型的指针(即一个 UTC 时间戳)。

  • 返回值:返回一个指向 struct tm 的指针,表示 本地时间结构

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],0 表示1月int tm_year;  // 自1900年以来的年数(如2025年为125)int tm_wday;  // 一周中的星期 [0,6](0 = 周日)int tm_yday;  // 一年中的日子 [0,365]int tm_isdst; // 夏令时标志(>0 表示夏令时,0 表示非夏令时,<0 表示未知)
};
函数输出的是…
gmtime()UTC 时间
localtime()本地时间(受系统时区影响)


六、gmtime(UTC0,不受时区影响)

struct tm *gmtime(const time_t *timep);

返回一个 struct tm * 类型的指针,指向的结构体内容表示该时间戳的 UTC 时间(非本地时间)

七、ctime(受时区影响)

时间戳(time_t)转换为可读字符串

#include <time.h>char *ctime(const time_t *timep);
  • 接收一个 time_t 类型的时间戳(通常由 time() 得到)

  • 返回一个静态字符串,表示本地时间的可读格式

ctime() 返回的字符串格式如下(固定 26 字节,包括换行符和终止符):

"Wed Apr 24 15:56:29 2025\n\0"
  • 返回的是一个静态字符数组的指针,不需要也不应该 free()

  • 非线程安全,因为内部使用的是共享的静态缓冲区(使用 ctime_r() 代替可实现线程安全)。

  • 总是根据本地时区来显示时间(和 localtime() 一致)。

如果你在上海(或者其他属于东八区的地方),ctime()自动使用当前系统设定的本地时区,也就是说:

假设你传入一个 time_t 值对应的是:

UTC 时间:2025-04-24 08:00:00

如果系统的本地时区是 Asia/Shanghai(UTC+8),那么:

printf("%s", ctime(&t));

输出会是:

Thu Apr 24 16:00:00 2025

自动加了 8 小时,因为本地时区就是比 UTC 快 8 小时。

八、asctime(不受时区影响)

struct tm 时间结构转成可读字符串的函数。

char *asctime(const struct tm *tm);
"Thu Apr 24 17:23:45 2025\n"

内容固定格式,长度固定为 26 字节(包括结尾的 \0)。

  • asctime() 返回的字符串是静态分配的(每次调用都会覆盖上一次结果)

  • 线程不安全(多线程用 asctime_r()

  • 格式无法自定义,适合简单显示,不适合精确格式控制(如 ISO 8601)

相关文章:

  • 基于SpringBoot+Vue的影视系统(源码+lw+部署文档+讲解),源码可白嫖!
  • 基于Vue3 的 h5监听从左到右手滑返回上一页
  • 省时省力的AI批量原创SEO文章生成工具解放双手
  • DevOps:概念与学习路径
  • Python 学习路线与笔记跳转(持续更新笔记链接)
  • arm-linux emmc镜像备份 和 rootfs镜像备份
  • vuex持久化vuex-persistedstate,存储的数据刷新页面后导致数据丢失
  • 从认证到透传:用 Nginx 为 EasySearch 构建一体化认证网关
  • 解决 Windows10 下 UWP 应用无法使用本地代理
  • 运维面试题01
  • 【C/C++】深入理解指针(四)
  • MySQL的下载、安装、配置
  • 【OpenCV图像处理实战】从基础操作到工业级应用
  • Python实例题:使用Pvthon3编写系列实用脚本
  • 想要从视频中提取背景音乐怎么搞?其实视频提取音频非常简单
  • 如何在Spring Boot中禁用Actuator端点安全性
  • Java集合框架解析
  • matplotlib1-画成对数据图
  • 类的六个默认成员函数
  • ssrf与xxe
  • 巴基斯坦最近“比较烦”:遣返阿富汗人或致地区局势更加动荡
  • 神舟二十号载人飞船发射升空
  • 封江晚开江早,东北地区主要江河上一冰封期冰层较常年偏薄
  • 大理洱源4.8级地震致442户房屋受损,无人员伤亡
  • 海关总署:明确部分货物、物品不再按进出境特殊物品监管
  • 北大学者:过度依赖技术工具可能会削弱人类主动思考的能力