Linux C编程基础:获取时间
1.前言
对于linux下的编程,无论是用户态还是内核态,时间获取都是经常需要使用到的。以下分别从用户态和内核态整理了几个常用的时间获取接口,供编写代码时快速查阅。
2.用户态获取时间
- 2.1 clock_gettime()
#include <time.h>int clock_gettime (clockid_t __clock_id, struct timespec *__tp);
作用:根据系统时钟的类型,获取当前时间__clock_id:系统时钟的类型。常用取值:- CLOCK_REALTIME: 从1970年1月1日到目前的时间
- CLOCK_MONOTONIC: 系统启动时间
- CLOCK_PROCESS_CPUTIME_ID: 本进程运行时间
- CLOCK_THREAD_CPUTIME_ID: 本线程运行的时间
__tp: 存放当前的时间。返回值:成功则返回0,失败则返回-1
timespec结构体:
struct timespec
{__time_t tv_sec; /* Seconds. 秒 */__syscall_slong_t tv_nsec; /* Nanoseconds. 纳秒*/
};
示例:
#include <stdio.h>
#include <string.h>
#include <time.h>long long get_clock_sys_time_ns(void)
{struct timespec tp;long long time_ns = 0;clock_gettime(CLOCK_MONOTONIC, &tp);time_ns = (long long)tp.tv_sec * 1000000000 + tp.tv_nsec;return time_ns;
}int main(void)
{struct timespec tp;///< 获取从1970年1月1日到目前的时间memset(&tp, 0, sizeof(struct timespec));clock_gettime(CLOCK_REALTIME, &tp);printf("clock_id = CLOCK_REALTIME, sec = %ld, nsec = %ld\n", tp.tv_sec, tp.tv_nsec);///< 获取系统启动时间memset(&tp, 0, sizeof(struct timespec));clock_gettime(CLOCK_MONOTONIC, &tp);printf("clock_id = CLOCK_MONOTONIC, sec = %ld, nsec = %ld, sys_time = %lld ns\n", tp.tv_sec, tp.tv_nsec, get_clock_sys_time_ns());///< 获取本进程运行时间memset(&tp, 0, sizeof(struct timespec));clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tp);printf("clock_id = CLOCK_PROCESS_CPUTIME_ID, sec = %ld, nsec = %ld\n", tp.tv_sec, tp.tv_nsec);///< 获取本线程运行时间memset(&tp, 0, sizeof(struct timespec));clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tp);printf("clock_id = CLOCK_THREAD_CPUTIME_ID, sec = %ld, nsec = %ld\n", tp.tv_sec, tp.tv_nsec);return 0;
}
- 2.2.gettimeofday()
#include <sys/time.h>int gettimeofday(struct timeval *tv, struct timezone *tz);
作用:获取当前时间(从1970年1月1日到目前的时间)tv:当前UTC时间tz:当前时区信息返回值:成功则返回0,失败则返回-1
timeval结构体:
struct timeval
{__time_t tv_sec; /* Seconds. 秒*/__suseconds_t tv_usec; /* Microseconds. 微秒*/
};
timezone结构体:
struct timezone{int tz_minuteswest; /* Minutes west of GMT. 和Greenwich时间差了多少分钟 */int tz_dsttime; /* Nonzero if DST is ever in effect. 日光节约时间的状态 */};
示例:
#include <stdio.h>
#include <string.h>
#include <sys/time.h>long long get_sys_time_ms(void)
{long long time_ms = 0;struct timeval tv;gettimeofday(&tv, NULL);time_ms = ((long long)tv.tv_sec*1000000 + tv.tv_usec) / 1000;return time_ms;
}int main(void)
{///< 获取系统时间printf("sys_time = %lld ms\n", get_sys_time_ms());return 0;
}
- 2.3.time()
#include <time.h>time_t time(time_t *tloc);
作用:获取1970-01-01 00:00:00 +0000至今的秒数(UTC)tloc:返回的秒存储指针返回值:成功则返回秒数,失败则返回-1,错误原因存在errno中。
time_t的类型:
typedef long time_t;
示例:
#include <stdio.h>
#include <time.h>time_t get_utc_time(void)
{return time(NULL);
}int main(int argc, char **argv)
{time_t utc_time = get_utc_time();printf("utc_time = %ld s\n", utc_time);return 0;
}
- 2.4.localtime()
#include <time.h>struct tm *localtime(const time_t *timep);
作用:将time_t类型的时间转换为struct tm类型的时间timep:当前UTC秒数返回值:返回当地时间
tm结构体:
struct tm
{int tm_sec; /* Seconds. [0-60] (1 leap second) */int tm_min; /* Minutes. [0-59] */int tm_hour; /* Hours. [0-23] */int tm_mday; /* Day. [1-31] */int tm_mon; /* Month. [0-11] 注意:0代表1月,以此类推*/int tm_year; /* Year - 1900. 该值为实际年份减去1900*/int tm_wday; /* Day of week. [0-6] 注意:0代表星期一,以此类推*/int tm_yday; /* Days in year.[0-365] 从每年的1月1日开始的天数,其中0代表1月1日,以此类推*/int tm_isdst; /* DST. [-1/0/1] 夏玲时标识符*/
};
示例:
#include <stdio.h>
#include <time.h>time_t get_utc_time(void)
{return time(NULL);
}int main(int argc, char **argv)
{time_t utc_time = get_utc_time();printf("utc_time = %ld s\n", utc_time);struct tm *local_tm = localtime(&utc_time); printf("local time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", local_tm->tm_year + 1900,local_tm->tm_mon + 1,local_tm->tm_mday,local_tm->tm_hour,local_tm->tm_min,local_tm->tm_sec);return 0;
}
- 2.5.localtime_r()
#include <time.h>struct tm *localtime_r(const time_t *timep, struct tm *result);
作用:将time_t类型的时间转换为struct tm类型的时间timep:当前UTC秒数result:当地时间返回值:返回当地时间
注:
localtime不是一个线程安全的函数。对于实时性要求较高的系统,多个线程同时调用localtime,可能会造成数据被覆盖。使用localtime_r来替代。
示例:
#include <stdio.h>
#include <time.h>time_t get_utc_time(void)
{return time(NULL);
}int main(int argc, char **argv)
{time_t utc_time = get_utc_time();printf("utc_time = %ld s\n", utc_time);struct tm result;struct tm *local_tm = localtime_r(&utc_time, &result); printf("local time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", local_tm->tm_year + 1900,local_tm->tm_mon + 1,local_tm->tm_mday,local_tm->tm_hour,local_tm->tm_min,local_tm->tm_sec);printf("result time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", result.tm_year + 1900,result.tm_mon + 1,result.tm_mday,result.tm_hour,result.tm_min,result.tm_sec);return 0;
}
- 2.6.gmtime()
#include <time.h>struct tm *gmtime(const time_t *timep);
作用:返回tm结构的GMT时间(UTC时间)timep:当前UTC秒数返回值:返回当地时间
例子:
#include <stdio.h>
#include <time.h>time_t get_utc_time(void)
{return time(NULL);
}int main(int argc, char **argv)
{time_t utc_time = get_utc_time();printf("utc_time = %ld s\n", utc_time);struct tm *gmt_tm = gmtime(&utc_time); printf("gmt time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", gmt_tm->tm_year + 1900,gmt_tm->tm_mon + 1,gmt_tm->tm_mday,gmt_tm->tm_hour,gmt_tm->tm_min,gmt_tm->tm_sec);return 0;
}
localtime和gmtime的区别:
localtime和gmtime都是C语言中的函数,用于将time_t类型的时间转换为struct tm类型的时间。它们的区别在于,gmtime将time_t转换为UTC时间,即世界标准时间,而localtime将time_t转换为本地时间。
例子:使用gmtime与localtime接口返回的小时数来计算当地时区
#include <stdio.h>
#include <time.h>time_t get_utc_time(void)
{return time(NULL);
}int main(int argc, char **argv)
{time_t utc_time = get_utc_time();printf("utc_time = %ld s\n", utc_time);struct tm *gmt_tm = gmtime(&utc_time); printf("gmt time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", gmt_tm->tm_year + 1900,gmt_tm->tm_mon + 1,gmt_tm->tm_mday,gmt_tm->tm_hour,gmt_tm->tm_min,gmt_tm->tm_sec);int gmt_hour = gmt_tm->tm_hour;struct tm *local_tm = localtime(&utc_time); printf("local time = %.4d-%.2d-%.2d %.2d:%.2d:%.2d\n", local_tm->tm_year + 1900,local_tm->tm_mon + 1,local_tm->tm_mday,local_tm->tm_hour,local_tm->tm_min,local_tm->tm_sec);int local_hour = local_tm->tm_hour;int local_time_zone = local_hour - gmt_hour;if (local_time_zone < -12) {local_time_zone += 24; } else if (local_time_zone > 12) {local_time_zone -= 24;}else{}printf("local_time_zone = %d\n", local_time_zone);return 0;
}
3.内核态获取时间
- 3.1.do_gettimeofday()(比较老的函数,新内核可能不存在了)
#include <linux/time.h> void do_gettimeofday(struct timeval *tv);
作用:与C标准库中gettimeofday()用法相同tv:当前UTC时间
timeval结构体:
struct timeval
{__time_t tv_sec; /* Seconds. 秒*/__suseconds_t tv_usec; /* Microseconds. 微秒*/
};
示例:
#include <linux/module.h>
#include<linux/time.h>
MODULE_LICENSE("GPL");int __init do_gettimeofday_init(void)
{printk("do_gettimeofday test begin.\n");struct timeval now={.tv_sec=0,.tv_usec=0}; //声明一个变量do_gettimeofday(&now); //调用函数获取时间,此时间是距离1970-01-01 00:00:00的时间/*显示当前时间差*/printk("the seconds of the day is: %ld\n", now.tv_sec); //秒数printk("the microseconds of the day is: %ld\n", now.tv_usec); //微秒数printk("do_gettimeofday test over.\n");return 0;
}void __exit do_gettimeofday_exit(void)
{printk("Goodbye do_gettimeofday test\n");
}module_init(do_gettimeofday_init);
module_exit(do_gettimeofday_exit);
-
3.2.基于ktime_t格式的时间
参考:linux kernel时钟获取 -
- ktime_get()
#include "linux/ktime.h"ktime_t ktime_get(void);作用:获取的是CLOCK_MONOTONIC时间。通过ktime_get获取的时间是不统计设备休眠时间的,并且这个时间统计的起始点则是设备启动后。
返回值:返回ktime_t格式的数据类型,单位为纳秒。ktime_t的定义:
typedef s64 ktime_t;示例:
time_test_drv_init ktime_t curTime = 0; curTime = ktime_get(); TIME_TEST_INFO("ktime_get:%lld ns", curTime); -
- ktime_get_ts64()
#include "linux/time64.h"void ktime_get_ts64(struct timespec64 *ts);作用:和ktime_get的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64。timespec64的定义如下:
struct timespec64 {time64_t tv_sec; /* seconds */long tv_nsec; /* nanoseconds */ };timespec64中包含了秒和纳秒,相对ktime_t纳秒这个时间表示更加适合人类查看.
示例:
static void show_time_ts64(const char* caller, const int line, const struct timespec64 *curTimeTs) {pr_info("%s,%d:%lld s %ld ns\n", caller, __LINE__, curTimeTs->tv_sec, curTimeTs->tv_nsec); }time_test_drv_init struct timespec64 curTimeTs; ktime_get_boottime_ts64(&curTimeTs); show_time_ts64(__func__, __LINE__, &curTimeTs); -
3.ktime_get_boottime()
static inline ktime_t ktime_get_boottime(void);作用:ktime_get_boottime获取的时间和ktime_get最大的不同是其包含了设备进入休眠的时间,其这个时间统计的起始点也是设备启动后。
返回值:返回值类型为ktime_t,单位为纳秒。示例:
time_test_drv_init ktime_t curTime = 0; curTime = ktime_get_boottime(); TIME_TEST_INFO("ktime_get_boottime:%lld ns", curTime); -
4.ktime_get_boottime_ts()
void ktime_get_boottime_ts64(struct timespec64 *);作用:ktime_get_boottime_ts相对于ktime_get_boottime的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64。 -
5.ktime_get_real()
ktime_t ktime_get_real(void);作用:ktime_get_real获取的时间的起点不是设备的启动时间点了,而是相对UTC的,即从1970开始。
示例:time_test_drv_init ktime_t curTime = 0; curTime = ktime_get_real(); TIME_TEST_INFO("ktime_get_real:%lld ns", curTime); -
6.ktime_get_real_ts()
void ktime_get_real_ts(struct timespec64 *);作用:ktime_get_real_ts相对于ktime_get_real的功能是完全一样的,区别在于对时间的表示数据类型由ktime_t变成了timespec64。
示例:time_test_drv_init struct timespec64 curTimeTs; ktime_get_real_ts64(&curTimeTs);
4.延时函数的实现
void delay_us(uint32_t nus)
{volatile uint32_t startts, endts, ts;ts = nus;startts = get_time_us();endts = startts + ts;if (endts > startts){while (get_time_us() < endts);}else{while (get_time_us() > endts);while (get_time_us() < endts);}
}
相关文章:
Linux C编程基础:获取时间
1.前言 对于linux下的编程,无论是用户态还是内核态,时间获取都是经常需要使用到的。以下分别从用户态和内核态整理了几个常用的时间获取接口,供编写代码时快速查阅。 2.用户态获取时间 2.1 clock_gettime() #include <time.h>int c…...
Spring核心注解
1、Bean注解 作用:用于把当前方法的返回值作为bean对象存入spring的ioc容器中位置: 一般出现在方法上面属性: name:用于指定bean的id。当不写时,默认值是当前方法的名称细节:当我们使用注解配置方法时,如果方法有参数,…...
哈希表原理,以及unordered_set/和unordered_map的封装和迭代器的实现
哈希表 unordered系列unordered_set和unordered_map的使用哈希哈希概念哈希冲突哈希函数闭散列开散列哈希表的扩容哈希表源码(开散列和闭散列) 封装unordered_set/和unordered_map,以及实现迭代器节点定义unordered_set定义unordered_map定义…...
如何把歌曲里的伴奏音乐提取出来,分享几个方法给大家!
对于一首歌,我们都知道,它有两部分组成:背景音乐人声。这两者合在一起,便是我们经常听的歌。部分用户想要直接获取歌曲伴奏,那么可以在UU伴奏网上下载。 操作方法比较简单,直接搜索想要的歌曲名称就可以了…...
区块链产业快速发展 和数集团开启区块链应用新时代
UTONMOS区块链游戏要来了。 就在5月底,UTONMOS品牌所属公司上海和数集团在泰国发布了【神念无界】系列的多款国际版链游,包括【神念无界-源起山海】、【北荒传奇】、【神宠岛】、【神农园】等区块链游戏。 以【神念无界-源起山海】为例,其是…...
初出茅庐的小李博客之常见字符串函数使用
C语言字符数组与字符串数组 在C语言中,字符数组和字符串数组实际上是同一种类型。字符串是由字符组成的字符数组,通常以空字符 ‘\0’ 结尾。C语言中的字符串是一种常见的数据类型。我们可以通过两种方式定义字符数组跟字符串数组 char charArray[10];…...
运筹学工程化流程和常见的运筹学算法分类以及常见软件
文章目录 前言运筹学工程化流程运筹学算法分类运筹学软件参考文献 前言 自2023年初新冠疫情管控放开后,各家公司各类岗位的人员都有被裁的消息传出,但用人市场上运筹学算法岗位却反其道行之,用工出现了激增。可以预见的是数据算法将从传统的…...
JAVA面向对象(三)
第三章 封装与继承 目录 第三章 封装与继承 1.1.封装 1.2.包 1.3.访问权限控制 1.4.static修饰符 1.4.1.成员变量 1.4.2.成员方法 1.4.3.代码块 总结 内容仅供学习交流,如有问题请留言或私信!!!!࿰…...
前端面试题---跨域处理和异常、错误处理
一.跨域处理 在前端开发中,当我们在浏览器中向不同域名或端口发起请求时,就会遇到跨域请求的限制。为了处理跨域请求,有几种常见的方法 1.JSONP(JSON with Padding) JSONP是一种利用 <script> 标签可以跨域加载…...
网络安全之反序列化漏洞分析
简介 FastJson 是 alibaba 的一款开源 JSON 解析库,可用于将 Java 对象转换为其 JSON 表示形式,也可以用于将 JSON 字符串转换为等效的 Java 对象分别通过toJSONString和parseObject/parse来实现序列化和反序列化。 使用 对于序列化的方法toJSONStrin…...
19 贝叶斯线性回归
文章目录 19 贝叶斯线性回归19.1 频率派线性回归19.2 Bayesian Method19.2.1 Inference问题19.2.2 Prediction问题 19 贝叶斯线性回归 19.1 频率派线性回归 数据与模型: 样本: { ( x i , y i ) } i 1 N , x i ∈ R p , y i ∈ R p {\lbrace (x_i, y_…...
第七十天学习记录:高等数学:微分(宋浩板书)
微分的定义 基本微分公式与法则 复合函数的微分 微分的几何意义 微分在近似计算中应用 sin(xy) sin(x)cos(y) cos(x)sin(y)可以用三角形的几何图形来进行证明。 假设在一个单位圆上,点A(x,y)的坐标为(x,y),点B(x’, y’)的坐标为(x’, y’)。则以两点…...
Jmeter
目录 一、jmeter 安装 二、jmeter 介绍 1、jmeter是什么? 2、jmeter 用来做什么? 3、优点 4、缺点 5、jmeter 目录介绍 ①_bin 目录介绍 ② docs 目录 — — 接口文档目录 ③ extras目录 — — 扩展插件目录 ④ lib 目录 — — 所用到的插件目录 ⑤ lic…...
Flutter 学习 之 时间转换工具类
Flutter 学习之时间转换工具类 在 Flutter 应用程序开发中,处理时间戳是非常常见的需求。我们通常需要将时间戳转换为人类可读的日期时间格式。为了实现这一点,我们可以创建一个时间转换工具类。 实现方法 以下是一个简单的时间转换工具类的示例&…...
docker consul
docker consul的容器服务更新与发现 服务注册与发现是微服务架构中不可或缺的重要组件,起始服务都是单节点的,不保障高可用性,也不考虑服务的承载压力,服务之间调用单纯的通过接口访问的,直到后来出现多个节点的分布式…...
全志V3S嵌入式驱动开发(开发环境再升级)
【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing 163.com】 前面我们陆陆续续开发了差不多有10个驱动,涉及到网口、串口、音频和视频等几个方面。但是整个开发的效率还是比较低的。每次开发调试的…...
ChatGPT:人工智能助手的新时代
ChatGPT:人工智能助手的新时代 文章目录 ChatGPT:人工智能助手的新时代引言ChatGPT的原理GPT-3.5架构概述预训练和微调过程生成式对话生成技术 ChatGPT的应用场景智能助理客服机器人虚拟角色教育辅助创意生成个性化推荐 ChatGPT的优势ChatGPT的使用技巧与…...
【面试】二、Java补充知识
JVM中的存储 JVM的五块存储区: 方法区(线程共享) 方法区用来存储类的各种信息(类名、方法信息等)、静态变量、常量和编译后的代码也存储在方法区中 方法区中也存在运行时常量池 常量池中会存放程序运行时生成的各种…...
LISTENER、TNSNAMES和SQLNET配置文件
LISTENER、TNSNAMES和SQLNET配置文件 用户连接验证listener.ora文件配置监听日志local_listener参数 tnsnames.ora文件配置 sqlnet.ora文件配置 用户连接验证 Oracle数据库中用户有三种常见的登录验证方式: 通过操作系统用户验证:必须是在数据库服务器…...
【Leetcode -225.用队列实现栈 -232.用栈实现队列】
Leetcode Leetcode -225.用队列实现栈Leetcode -232.用栈实现队列 Leetcode -225.用队列实现栈 题目:仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 …...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
模型参数、模型存储精度、参数与显存
模型参数量衡量单位 M:百万(Million) B:十亿(Billion) 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的,但是一个参数所表示多少字节不一定,需要看这个参数以什么…...
自然语言处理——循环神经网络
自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元(GRU)长短期记忆神经网络(LSTM)…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
TCP/IP 网络编程 | 服务端 客户端的封装
设计模式 文章目录 设计模式一、socket.h 接口(interface)二、socket.cpp 实现(implementation)三、server.cpp 使用封装(main 函数)四、client.cpp 使用封装(main 函数)五、退出方法…...
Java后端检查空条件查询
通过抛出运行异常:throw new RuntimeException("请输入查询条件!");BranchWarehouseServiceImpl.java // 查询试剂交易(入库/出库)记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...
负载均衡器》》LVS、Nginx、HAproxy 区别
虚拟主机 先4,后7...
网页端 js 读取发票里的二维码信息(图片和PDF格式)
起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的ÿ…...
