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)。 …...

(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
【解密LSTM、GRU如何解决传统RNN梯度消失问题】
解密LSTM与GRU:如何让RNN变得更聪明? 在深度学习的世界里,循环神经网络(RNN)以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而,传统RNN存在的一个严重问题——梯度消失&#…...
MVC 数据库
MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...
现有的 Redis 分布式锁库(如 Redisson)提供了哪些便利?
现有的 Redis 分布式锁库(如 Redisson)相比于开发者自己基于 Redis 命令(如 SETNX, EXPIRE, DEL)手动实现分布式锁,提供了巨大的便利性和健壮性。主要体现在以下几个方面: 原子性保证 (Atomicity)ÿ…...

2025年渗透测试面试题总结-腾讯[实习]科恩实验室-安全工程师(题目+回答)
安全领域各种资源,学习文档,以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各种好玩的项目及好用的工具,欢迎关注。 目录 腾讯[实习]科恩实验室-安全工程师 一、网络与协议 1. TCP三次握手 2. SYN扫描原理 3. HTTPS证书机制 二…...

Linux部署私有文件管理系统MinIO
最近需要用到一个文件管理服务,但是又不想花钱,所以就想着自己搭建一个,刚好我们用的一个开源框架已经集成了MinIO,所以就选了这个 我这边对文件服务性能要求不是太高,单机版就可以 安装非常简单,几个命令就…...

Elastic 获得 AWS 教育 ISV 合作伙伴资质,进一步增强教育解决方案产品组合
作者:来自 Elastic Udayasimha Theepireddy (Uday), Brian Bergholm, Marianna Jonsdottir 通过搜索 AI 和云创新推动教育领域的数字化转型。 我们非常高兴地宣布,Elastic 已获得 AWS 教育 ISV 合作伙伴资质。这一重要认证表明,Elastic 作为 …...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...
Java详解LeetCode 热题 100(26):LeetCode 142. 环形链表 II(Linked List Cycle II)详解
文章目录 1. 题目描述1.1 链表节点定义 2. 理解题目2.1 问题可视化2.2 核心挑战 3. 解法一:HashSet 标记访问法3.1 算法思路3.2 Java代码实现3.3 详细执行过程演示3.4 执行结果示例3.5 复杂度分析3.6 优缺点分析 4. 解法二:Floyd 快慢指针法(…...