引言
从整理到最后,我越来越觉得通过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 value */
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; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
这里多了参数tz,其结构体声明如下:
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of DST correction */
};
看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; /* seconds */
long tv_nsec; /* nanoseconds */
};
参数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; /* Seconds since boot */
unsigned long loads[3]; /* 1, 5, and 15 minute load averages */
unsigned long totalram; /* Total usable main memory size */
unsigned long freeram; /* Available memory size */
unsigned long sharedram; /* Amount of shared memory */
unsigned long bufferram; /* Memory used by buffers */
unsigned long totalswap; /* Total swap space size */
unsigned long freeswap; /* swap space still available */
unsigned short procs; /* Number of current processes */
unsigned long totalhigh; /* Total high memory size */
unsigned long freehigh; /* Available high memory size */
unsigned int mem_unit; /* Memory unit size in bytes */
char _f[20-2*sizeof(long)-sizeof(int)]; /* Padding for libc5 */
};
设置时间函数
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; /* seconds 0~59,能到达60做闰秒 */
int tm_min; /* minutes 0~59 */
int tm_hour; /* hours 0~23 */
int tm_mday; /* day of the month 1~31 */
int tm_mon; /* month 0~11 */
int tm_year; /* year 自1900年*/
int tm_wday; /* day of the week 自星期日起 0~6*/
int tm_yday; /* day in the year 自一月一日起 0~365*/
int tm_isdst; /* daylight saving time 夏令时标志,正表示启用,0表示不请用,负表示不可用的*/
};
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。