自从时间在人类思想中诞生以来,它就作为一个永恒的标杆,竖立在每个人心中。程序员眼中的时间是毫秒级别的,所以这些人在程序中对时间的控制与获取是极为重视的。
linux作为一个维护多年健壮的内核,它对时间的编程也是服务周到的,程序员可以通过一些相关API获取 世界标准时间(UTC),本地时间,系统时间等,也可以通过定时器控制自己的代码运行,而且这些API也有不同时间精度,不同精度适用于不同环境场合,使得linux时间编程更灵活。
本帖转自:http://blog.csdn.net/jiebaoabcabc/article/details/36919515
一、时间的类型
1.格林威治标准时间
coordinated universal time(UTC)是世界标准时间,即常说的格林威治标准时间(greenwich mean time,GMT).
2.日历时间
日历时间(calendar time)是用"一个标准时间点(如1970年1月1日0点)到此时经过的秒数"来表示的时间.
二、时间的获取
在程序当中, 我们经常要输出系统当前的时间,比如日志文件中的每一个事件都要记录其产生时间。在 C 语言中获取当前时间的方法有以下几种,它们所获得的时间精度从秒级到纳秒,各有所不同。
C 时间函数
| function 定义 | 含义 | 返回值 | 精度 |
|---|---|---|---|
| time() | time 函数获得从 1970 年 1 月 1 日 0 点到当前的秒数,存储在time_t结构之中。 | time_t | 秒 |
| gettimeofday() | gettimeofday 函数返回从 1970 年 1 月 1 日 0 点以来,到现在的时间。用 timeval 数据结构表示。 | struct timeval{time_t tv_sec;long int tv_usec;}; | 微秒 |
| clock_gettime() | clock_gettime 函数返回从 1970 年 1 月 1 日 0 点以来,到现在的时间。用 timespec 数据结构表示。 支持不广泛,属于实时扩展,多用于嵌入式linux中。 | struct timespec{time_t tv_sec;long int tv_nsec;}; | 纳秒 |
linux提供的时间是一个 从 1970 年 1 月 1 日 0 点以来,到现在的时间秒计数值,如果程序员仅仅要获取直观的年月日形式的时间格式,那么就需要进行转换了。
由于国家,习惯和时区的不同,时间的表示方法并没有一个统一的格式。为了满足各种时间显示的需求,标准 C 库提供了许多时间格式转换的函数。这些函数的数量众多,容易让人迷惑,记住它们的用法十分不易。在这里我借用 Michael Kerrisk 在《Linux Programming Interface》一书中的插图,来对这些标准 C 函数进行一个总体的概览。
图 1. 各种时间显示格式转换函数关系图
通过这幅图应该能很直观的看到linux时间格式转换的流程。
四、时间函数的API
时间函数的API均属于系统调用函数.。
1.获取日历时间
#include <time.h>// Glibc
time_t time(time_t *t)// 获取时间
函数功能: 获取日历时间,即从1970年1月1日0点到现在所经历的秒数.
参数: 通常设置为NULL,也可以通过传入time_t类型变量的地址来获取时间
time_t stime(const time_t *when)// 设置时间
函数功能: 设置日历时间,即从1970年1月1日0点到现在所经历的秒数.
参数: 通常通过strptime->mktime->stime自定义格式时间格式设置时间
time_t在time.h中定义:typedef long int time_t)
例:
#include <stdio.h>
#include <time.h>
void main()
{
long int seconds=0;
seconds = time(NULL);
printf("seconds=%d\n",seconds);
}
2.将日历时间转换为格林威治标准时间
struct tm *gmtime(const time_t *timep)
函数功能:将日历时间转化为格林威治标准时间,并保存在tm结构
参数:日历时间的返回值
3.将日历时间转化为本地时间
struct tm* localtime(const time_t *timep)
函数功能:将日历时间转化为本地时间,并保存至tm结构
参数:日历时间的返回值
由上面两个函数可以看出,这两个函数的返回值均存放在tm结构中,具体的tm结构如下:
struct tm
{
int tm_sec; //秒值
int tm_min; //分钟值
int tm_hour; //小时值
int tm_mday; //本月第几日
int tm_mon; //本年第几月
int tm_year; //tm_year+1900=哪一年
int tm_wday; //本周第几日
int tm_yday; //本年第几日
int tm_isdst; //日光节约时间
}
char *asctime(const struct tm *tm)
函数功能:将tm格式的时间转化为字符串
参数:日历时间的返回值
例如: SAT Jul 30 08:43:03 2005
该函数较ctime()使用起来更加的复杂.必须按照下面3个步骤来进行.
<1>使用函数time()来获取日历时间
<2>使用函数gmtime()将日历时间转化为格林威治标准时间
<3>使用函数asctime()将tm格式的时间转化为字符串
#include <stdio.h>
#include <time.h>
int main ()
{
time_t time_raw_format;
struct tm * time_struct;
char buf [64];
time ( &time_raw_format );
// gmtime : time_t -> tm 此函数返回的时间日期未经时区转换,而是UTC时间
time_struct = gmtime ( &time_raw_format );
// mktime : tm -> time_t
mktime(&time_raw_format);
// asctime : tm -> time string string have a '\n'
printf("%s", asctime(time_struct));
// strftime : tm -> user time string It is now: 04:27PM.
strftime (buf,64,"It is now: %I:%M%p.",time_struct);
// strptime : user time string -> tm set time
//strptime("2000-01-01-00:00:00", "%Y-%m-%d-%H:%M:%S", time_struct);
puts (buf);
return 0;
}
char *ctime(const time_t *timep)
函数功能:将日历时间转化为本地时间的字符串形式
参数:日历时间的返回值
该函数较asctime()使用起来更加简单.必须按照下面2个步骤来进行.
<1>使用函数time()来获取日历时间
<2>使用函数ctime()将日历时间直接转化为字符串
#include <stdio.h>
#include <time.h>
int main ()
{
time_t time_raw_format;
time ( &time_raw_format ); //获取当前时间
printf (" time is [%d]\n", time_raw_format);
//用 ctime 将时间转换为字符串输出
printf ( "The current local time: %s\n", ctime(&time_raw_format));
// stime set time
printf ( "The current local time: %s\n", stime(&time_raw_format));
return 0;
}
int gettimeofday(struct timeval *tv,struct timezone *tz)
函数功能:获取从今日凌晨(0:0:0)到现在的时间差,常用于计算事件耗时
参数1:存放从今日凌晨(0:0:0)到现在的时间差,时间差以秒或微秒为单位,以结构体形式存放
struct timeval
{
int tv_sec; //秒数
int tv_usec; //微秒数
}
参数2:常设置为null
函数用法:可以在做某件事情之前调用gettimeofday(),在做完该件事情之后调用gettimeofday(),两个函数的参数1的差就是做该事情所消耗的时间.
#include <stdio.h>
#include <time.h>
#include <math.h> // -lm
#include <sys/time.h> // timeval gettimeofday
#include <stdlib.h> // exit
float
measureTime(struct timeval *start, struct timeval *stop);
void function()
{
unsigned int i,j;
double y;
for(i=0;i<1000;i++)
for(j=0;j<1000;j++)
y=sin((double)i); //耗时操作
}
int main()
{
struct timeval tpstart,tpend;
float timeuse;
gettimeofday(&tpstart,NULL); //记录开始时间戳
function();
gettimeofday(&tpend,NULL); //记录结束时间戳
timeuse = measureTime(&tpstart, &tpend);
printf("Used Time:%f\n",timeuse);
exit(0);
}
float
measureTime(struct timeval *start, struct timeval *stop)
{
float timeuse;
timeuse = 1000000*(stop-> tv_sec - start-> tv_sec)+
stop-> tv_usec - start-> tv_usec; //计算差值
return timeuse /= 1000000; // sec
}
由于用到了数学函数库,编译时要加上链接参数-lm
6.超强实时性 获取纳秒级精度时间函数
intclock_gettime(clockid_t clk_id,structtimespec *tp);
函数功能:函数"clock_gettime"是基于Linux C语言的时间函数,他可以用于计算精度和纳秒
Get current value of CLOCK and store it in TP.
参数
struct timespec {
<span style="white-space:pre"> </span>time_t tv_sec; <span style="white-space:pre"> </span>/* 秒*/
<span style="white-space:pre"> </span>long tv_nsec; <span style="white-space:pre"> </span>/* 纳秒*/
};
例:提供一个ms秒数转换成timespec类型的纳秒级函数,可以应用到很多程序中,比如有超时设置的pthread mutex之类的啦。
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <time.h> // clock_gettime
#include <errno.h>
#define NO_WAIT 0
#define WAIT_FOREVER (-1)
// ms -> timespec(sec and nsec)
static inline void getTimespec(int wait_ms, struct timespec *tp)
{
time_t sec, t;
long long nsec;
sec = 0;
if (wait_ms == NO_WAIT)
{
nsec = 0;
}
else
{
nsec = wait_ms * 1000000LL;
}
if (clock_gettime(CLOCK_REALTIME, tp) == -1) //get now time
{
printf("getTimespec: clock_gettime call fail, error %d(%s)\n", errno, strerror(errno));
tp->tv_sec = time(NULL) + 1;
tp->tv_nsec = 0;
}
else
{
t = time(NULL) + 1;
if ((int)(tp->tv_sec - t) > 30)
{
tp->tv_sec = t;
tp->tv_nsec = 0;
}
}
nsec += tp->tv_nsec;
// printf("getTimespec: current time sec = %ld, time = %ld, nsec = %ld, total nsec = %lld\n", tp->tv_sec, time(NULL)+1, tp->tv_nsec, nsec);
if (nsec >= 1000000000) // if nsec > 1sec
{
sec = nsec / 1000000000;
nsec = nsec % 1000000000;
}
tp->tv_sec += sec;
tp->tv_nsec = nsec;
// printf("getTimespec: after time sec = %ld, time = %ld, nsec = %ld\n", tp->tv_sec, time(NULL)+1, tp->tv_nsec);
return;
}
<1>使程序睡眠seconds秒
unsigned int sleep(unsigned int seconds)
函数功能:使程序睡眠seconds秒
参数:需要休眠的秒数
<2>使程序睡眠usec微秒
void usleep(unsigned long usec)
函数功能:使程序睡眠usec微秒
参数:需要休眠的秒数
五、小结
今天罗列了linux中常见的时间获取API和一些简单的相关例子,linux的时间编程(二) - 定时器 中将讲述linux中定时器的常用API和相关应用。
本文介绍了Linux下的时间编程,包括时间类型如UTC和日历时间,以及获取时间的C语言函数,如`time()`、`gmtime()`、`localtime()`、`ctime()`、`gettimeofday()`等,还提到了高精度的`clock_gettime()`函数和睡眠函数。

1458

被折叠的 条评论
为什么被折叠?



