前言

我们在linux平台进行开发时,时间相关的操作基本上都会遇到,本文就对常用的时间相关的结构体、接口进行分析小结。

常见类型、结构体定义

timespec

原型

struct timespec
{__time_t tv_sec;       /* Seconds. 秒 */__syscall_slong_t tv_nsec;  /* Nanoseconds.  纳秒*/
};

说明

该结构体只是包括秒和纳秒,并没有任何其他含义,比如1970年以来的秒数等。只是个存放空间。为clock_gettime的出参。

clock_gettime

原型

int clock_gettime (clockid_t __clock_id, struct timespec *__tp);

说明

根据clock_id(系统时钟)的类型,获取当前时间。

参数说明

clock_id常用取值枚举说明

枚举值 说明
CLOCK_REALTIME 系统当前时间,从1970年1月1日算起
CLOCK_MONOTONIC 从系统启动时间算起,经过的时间
CLOCK_PROCESS_CPUTIME_ID 本进程运行时间
CLOCK_THREAD_CPUTIME_ID 本线程运行的时间

程序示例

#include <time.h>
#include <stdio.h>
#include <sys/time.h>int main(void)
{struct timespec tsp;printf("CLOCK REALTIME time:\n");clock_gettime(CLOCK_REALTIME, &tsp);printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);printf("-----------------------\n");printf("CLOCK MONOTONIC time:\n");clock_gettime(CLOCK_MONOTONIC, &tsp);printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);printf("-----------------------\n");printf("CLOCK PROCESS CPUTIME ID time:\n");clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &tsp);printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);printf("-----------------------\n");printf("CLOCK THREAD CPUTIME ID time:\n");clock_gettime(CLOCK_THREAD_CPUTIME_ID, &tsp);printf("sec:%ld, nsec:%ld\n", tsp.tv_sec, tsp.tv_nsec);printf("-----------------------\n");return 0;
}

运行结果:

CLOCK REALTIME time:
sec:1644155596, nsec:748701786
-----------------------
CLOCK MONOTONIC time:
sec:12526311, nsec:817330221
-----------------------
CLOCK PROCESS CPUTIME ID time:
sec:0, nsec:585929
-----------------------
CLOCK THREAD CPUTIME ID time:
sec:0, nsec:590570

timeval

原型

struct timeval
{__time_t tv_sec;       /* Seconds.  秒*/__suseconds_t tv_usec;  /* Microseconds.  微秒*/
};

说明

该结构体只是包括秒和微秒,并没有任何其他含义,比如1970年以来的秒数等。只是个存放空间。为gettimeofday的出参。

timezone

原型

struct timezone{int tz_minuteswest;      /* Minutes west of GMT. 和Greenwich时间差了多少分钟 */int tz_dsttime;        /* Nonzero if DST is ever in effect. 日光节约时间的状态  */};

说明

该结构体为时区相关信息,用的比较少,gettimeofday的出参。一般我们也可以直接传入NULL.

gettimeofday

原型

int gettimeofday(struct timeval *tv, struct timezone *tz);

说明

获取当前时间,为UTC时间,1970年以来的秒+微秒、时区信息。

参数说明

参数 类型 说明
tv struct timeval * 出参,当前UTC时间
tz struct timezone * 当前时区信息

返回值

成功则返回0,失败则返回-1,错误原因存在errno中。

程序示例

#include <time.h>
#include <stdio.h>
#include <sys/time.h>int main(void)
{struct timeval tv;struct timezone tz;printf("gettimeofday time:\n");gettimeofday(&tv, &tz);printf("tv_sec:%ld tv_usec:%ld\n", tv.tv_sec, tv.tv_usec);printf("tz:%d %d\n", tz.tz_dsttime, tz.tz_minuteswest);return 0;
}

运行结果:

gettimeofday time:
tv_sec:1644156383 tv_usec:513679
tz:0 0

time_t

原型

typedef long time_t;

说明

该类型其实就是long int ,用于存储秒数,是time函数的入参和返回值。

time

原型

time_t time(time_t *t)

说明

该函数会返回从1970年1月1日0时0秒算起到现在所经过的秒数,如果t为非空指针的话,该函数还会将返回值存储到t指针所指的内存里。

参数说明

参数 类型 说明
t time_t * 返回的秒存储指针

返回值

成功则返回秒数,失败则返回-1,错误原因存在errno中。

程序示例

#include <time.h>
#include <stdio.h>
#include <sys/time.h>int main(void)
{time_t timep1, timep2;timep1 = time(NULL);time(&timep2);printf("timep1:%ld  timep2:%ld\n", timep1, timep2);return 0;
}

运行结果:

timep1:1644157011  timep2:1644157011

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] 夏玲时标识符*/
};

说明

该类型用于描述真实世界所使用的时间日期,包括年月日时分秒周等, 是localtime的返回值

localtime

原型

struct tm *localtime(const time_t *timep);

说明

将参数timep所指的当前秒数转换成真实世界所使用的时间日期表示方法,结果返回。

参数说明

参数 类型 说明
timep time_t 当前UTC秒数

返回值

当前UTC秒数对应的年月日时分秒周等。

程序示例

#include <time.h>
#include <stdio.h>
#include <sys/time.h>int main(void)
{time_t timep;struct tm *p;timep = time(NULL);printf("timep:%ld\n", timep);p = localtime(&timep);// 对年、月要进行相应的处理printf("%d-%d-%d %d:%d:%d \n", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec);return 0;
}

运行结果:

timep:1644157741
2022-2-6 22:29:1

localtime_r

在上面localtime的程序示例中,可以发现,localtime的返回值是 struct tm *类型,也就是指向struct tm类型的指针,这样使用并不会造成内存泄露等问题,这是因为localtime的返回值其实指向了一个静态变量,这是静态库已经定义的static struct tm类型数据,很明显,由于程序使用静态变量,会导致localtime不可重入,也就是非现成安全,对于一般的应用场景并不会带来什么隐患,但是对于实时性要求高的场所,会带来问题,因为多次调用localtime会造成返回值覆盖。

比如:

两个线程A和B同时调用 localtime 函数:

时刻1:线程A调用 localtime 函数,得到一个指针,tm中存储的值更新为 value-A

时刻2:线程B调用 localtime 函数,得到一个指针, tm中存储的值更新为 value-B

时刻3:线程A对 localtime 返回的指针进行相关引用操作(例如 printf 输出某字段),此时 static struct tm 中的值实际是 value-b,并非预期的 value-a

时刻4:线程B对 localtime 返回的指针进行相关引用操作,此时 static struct tm 中的值实际是 value-b

所以为了解决localtime不可重入的问题,就出现了localtime_r。

原型

struct tm *localtime_r(const time_t *timep, struct tm *result);

说明

调用 localtime 只需要传入指向 time_t 的一个常量指针;

调用 localtime_t 不仅需要传入指向 time_t 的一个常量指针,还需要传入指向 struct tm 的一个指针,结果将存储在 result 指向的 struct tm 对象中;

程序示例

#include <time.h>
#include <stdio.h>
#include <sys/time.h>int main(void)
{time_t timep;struct tm *p;struct tm res;timep = time(NULL);printf("timep:%ld\n", timep);localtime_r(&timep, &res);printf("%d-%d-%d %d:%d:%d \n", 1900 + res.tm_year, 1 + res.tm_mon, res.tm_mday, res.tm_hour, res.tm_min, res.tm_sec);return 0;
}

运行结果:

timep:1644158806
2022-2-6 22:46:46

小结

以上为linux平台下,与时间相关的常用结构体、变量、接口定义,再详细的说明可以参考相关源码定义。

Linux时间相关知识小结:struct timeval、timespec、gettimeofday、time、localtime....相关推荐

  1. struct timeval结构体 以及 gettimeofday()函数、struct timespec结构体

    struct timeval结构体 struct timeval结构体在time.h中的定义为: struct timeval { __time_t tv_sec; /* Seconds. */ __ ...

  2. Linux高精度struct timespec和struct timeval

    1. 结构基本定义 1.1 struct timespec 定义 typedef long time_t; #ifndef _TIMESPEC #define _TIMESPEC struct tim ...

  3. Linux高精度struct timespec 和 struct timeval

    struct timespec now_ts;clock_gettime(CLOCK_MONOTONIC, &now_ts);printf("os tick times, %ld s ...

  4. struct timespec 和 struct timeval

    struct timespec 和 struct timeval time()提供了秒级的精确度 . 1.头文件 <time.h> 2.函数原型 time_t time(time_t * ...

  5. struct timeval的处理(timeval比较及相减)

    timeval结构体的处理函数 timeval的大小比较 timeval转为double类型的秒 两个timeval类型之间的时间差 函数耗时测试 timeval的大小比较 /************ ...

  6. struct timeval 和 struct timespec 应用小结

    在基于linux的C编程中,经常会看到 struct timeval和struct timespec 这两个跟时间有关的结构体,有时候会容易混淆,先看下这两个结构体的定义,以linux-2.6.35为 ...

  7. linux系统中struct timeval结构体、struct timezone结构体以及gettimeofday函数

    格林尼治时间.协调世界时 间.世界时间.日光节约时间以及时区等介绍: 格林尼治时间(Greenwich Mean Time,GMT)是指位于英国伦敦郊区的皇家格林尼治天文台当地的标准时间,因为本初子午 ...

  8. Linux tm time_t timeval timespec以及与时间相关函数用法

    一.时间类型 linux中编程通常需要用到时间变量,和相关的时间操作函数.常用的时间类型有: time_t .struct  timeval.struct   timespec.struct   tm ...

  9. linux下的ktime_t timeval timespec

    内核中,经常看到ktime_t变量,总结下 ktime_t Nanosecond//纳秒 /* Nanosecond scalar representation for kernel time val ...

最新文章

  1. 使用python愉快地做高数线代题目~
  2. 用Python防止头上一片青青草原
  3. Github上十大热门可视化面板!再也不用担心画图啦!
  4. .NET3.5中的高性能 Socket API
  5. Ubuntu上面安装Redis Python
  6. angular 动画_如何在Angular 6中使用动画
  7. 19.Delete Documents-官方文档摘录
  8. PostgreSQL 10 自定义并行计算聚合函数的原理与实践
  9. 开菜鸟驿站需要什么条件?投入成本大概要多少?
  10. 二下语文书电子课本_沪教版牛津英语小学五年级上册高清电子课本教材书(三年级起点)...
  11. ValueError: This model has not yet been built. Build the model first by calling `build()` or calling
  12. 一篇文章教你用matlab求定积分广义/变限积分
  13. mac 编译mysql 源码_Mac上编译MySQL源码与安装
  14. 怎样绘制流程图?分享拼多多购物流程图模板及绘制技巧
  15. Android一键加群实现
  16. OJ一元二次方程的根*易错点
  17. Audio Hijack for Mac(音频录制工具)
  18. IMDB算法(贝叶斯算法)
  19. 从中国的山水画谈谈游戏场景设计该有的状态
  20. 用新华字典来彻底解释清:数据库索引到底是什么

热门文章

  1. 鱼群算法在上网行为管理系统中可以起到怎样的作用
  2. Python爬虫突破封禁的6种常见方法
  3. [RK3399][Android7.1.1]Android->输入法:设置默认输入法及输入法相关设置
  4. Php / Thinkphp 之 使用phpqrcode 生成自定义二维码
  5. php opcache 作者,PHP Opcache配置
  6. 复星旅文拟12月中旬上市:最高募资42亿港元 淘宝做基石投资
  7. Mosh Python 学习笔记
  8. postman在线测试webservice调用
  9. C#打开docx文件 (其他文件类似)
  10. Java 泛型中的通配符详解