引言
从整理到最后,我越来越觉得通过man手册去了解一个函数更好,虽然英文水平差了点,读起来吃力甚至看不懂啥意思,但坚持看,又提升英语,弄明白之后也方便之后查询别的函数,所以在此还是要说明下,通过man手册来查询函数,还是很有必要的!当然我整理了还是发表下~ 这过程中也学了不少东西。中间有错误不完善的地方,望指正,谢谢!
术语介绍
- Epoch指的是一个特定的时间:1970-01-01 00:00:00 UTC。
- UTC:协调世界时(Universal Time Coordinated),各时区以其进行时间校准
- GMT:格林威治标志时间,原作为标准时间使用,因存在时间偏差,现用UTC
- 时区:如北京在东八区,其时区名与UTC的偏移量 (CCT+8:00),表示北京时间比UTC时间慢8小时,如果得知北京时间算UTC时间,则是-8小时
- DST daylight saving time 夏时制 ,又称夏令时。因夏天天亮的早,人为的将时间修改提前,就可以使人早睡早起,节约照明时间,从而节约能源。
辅助时间命令
- date 可查看设置系统时间
- hwclock 可查看设置RTC时间,需要超级权限
获取时间函数
time
#include <time.h>
typedef long time_t;
time_t time(time_t *t);
函数返回的是当前UTC时间自Epoch经过的秒数,而不是你本地时间自Epoch经过的秒数,如果参数t不为空,则也将返回值保存至该参数指向的内存中。
gettimeofday
gettimeofday与time功能一样,获取自Epoch经过的时间,只是相对更精确,单位可至微秒,其函数声明如下:
#include <sys/time.h>
int gettimeofday(struct timeval *tv, struct timezone *tz);
结构体
struct timeval
{
time_t tv_sec;
suseconds_t tv_usec;
};
这里多了参数tz,其结构体声明如下:
struct timezone {
int tz_minuteswest;
int tz_dsttime;
};
看man手册说“The use of the timezone structure is obsolete, the tz argument should normally be specified as NULL”,所以在使用gettimeofday的时候,第二个参数应该设置为NULL。
在看CONFORMING TO说明中,推荐使用clock_gettime替代gettimeofday。
clock_gettime
clock_gettime比gettimeofday获取的时间更为精确,可精确到纳秒。但除像gettimeofday获取自Epoch经过的时间,还可以获取自系统启动经过的时间等,具体看clk_id参数设置。函数原型如下:
#include <time.h>
int clock_gettime(clockid_t clk_id, struct timespec *tp);
链接的时候加上选项 -lrt
结构体
struct timespec {
time_t tv_sec;
long tv_nsec;
};
参数clk_id类型有:
CLOCK_REALTIME:获取自Epoch经过的时间
CLOCK_MONOTONIC:获取自系统启动经过的时间
CLOCK_PROCESS_CPUTIME_ID:进程运行的CPU时间
CLOCK_THREAD_CPUTIME_ID:线程运行的CPU时间
sysinfo
除了clock_gettime可得知系统启动运行时间,sysinfo函数也可以获取自系统启动的时间
#include <sys/sysinfo.h>
int sysinfo(struct sysinfo *info);
结构体
Since Linux 2.3.23 (i386), 2.3.48 (all architectures) the structure is:
struct sysinfo {
long uptime;
unsigned long loads[3];
unsigned long totalram;
unsigned long freeram;
unsigned long sharedram;
unsigned long bufferram;
unsigned long totalswap;
unsigned long freeswap;
unsigned short procs;
unsigned long totalhigh;
unsigned long freehigh;
unsigned int mem_unit;
char _f[20-2*sizeof(long)-sizeof(int)];
};
设置时间函数
settimeofday
与gettimeofday相对的是 settimeofday,函数声明如下:
int settimeofday(const struct timeval *tv, const struct timezone *tz);
settimeofday改的是系统时间,并没有改RTC时间,重启后内核读取RTC时间来初始化系统时间。
参数tv基于UTC时间偏差的秒数,相应增减当前的系统时间,tz参数则仍旧使用NULL。
该函数的执行需要用户具有超级权限。
stime
#include <time.h>
int stime(time_t *t);
stime的功能可以说和settimeofday是一样的,同样也需要超级权限才能执行。
clock_settime
与clock_gettime相对的是clock_settime
int clock_settime(clockid_t clk_id, const struct timespec *tp);
但其不能对系统运行时间进行设置。
转换时间函数
最开始介绍的获取时间函数并不易于查看,通过以下函数,可以转换成易于阅读的时间格式。
#include <time.h>
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
time_t mktime(struct tm*tm);
结构体:
struct tm {
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
gmtime函数和localtime函数可以将time_t类型数据转化成struct tm结构体类型数据,所不同的是gmtime转化的是基于UTC的tm结构体,而localtime则会转化成基于当地时区的tm结构体。
asctime和ctime都是返回字符串格式的时间,其格式是“星期 月份 日期 时:分:秒 年份\n”,不同的是ctime传入的是time_t *类型数据,而asctime传入的是struct tm *类型数据。
ctime(t) 相当于 asctime(localtime(t)),t是同一个参数;就是ctime直接调用time返回的UTC时间,转换成当地的可读时间,而asctime需将time返回的时间先转化成当地的tm结构体再转换成当地可读的时间。
mktime则可以将tm结构体转换成time_t类型数据,需要注意的是它把入参作为UTC时间,忽略tm结构体中的成员变量tm_wday和tm_yday,并转换成当地时区的time_t。
最后同一功能的函数名加_r后缀的则是可重入函数,使用自己申请的内存来保存结果。