Linux下C语言开发,经常需要获取系统时间或做延时操作。Linux提供了一些应用层库函数,基本可以满足开发中的不同需求。现在简单整理一下Linux下的时间函数。

主要分为两类:时间获取函数 和 延时函数。

时间获取函数

1. gettimeofday

函数原型:

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

用到的结构体

1
2
3
4
5
6
7
8
9
struct  timezone{
int tz_minuteswest;/*和greenwich 时间差了多少分钟*/
int tz_dsttime;/*type of DST correction*/
};

struct timeval {
long tv_sec; /* 秒 */
long tv_usec; /* 微秒 */
};

在gettimeofday()函数中tv或者tz都可以为空,如果为空则就不返回其对应的结构体。

函数执行成功后返回0,失败后返回-1,错误代码存于errno中。

示例:

1
2
3
4
5
6
7
long time_msec(void)
{
struct timeval tv;
gettimeofday(&tv, NULL);

return tv.tv_sec * 1000 + tv.tv_usec/1000;
}

2. clock_gettime

函数原型:

1
int clock_gettime(clockid_t clk_id, struct timespec *tp)

clock_gettime的用法与gettimefday类似,精度上提供了纳秒级精度,而且效率更高。

用到的结构体

1
2
3
4
struct timespec {
long tv_sec; /* 秒 */
long tv_nsec; /* 纳秒 */
};

clk_id参数解释:

(1) CLOCK_REALTIME:系统实时时间,随系统实时时间改变而改变,即从UTC1970-1-1 0:0:0开始计时,中间时刻如果系统时间被用户该成其他,则对应的时间相应改变

(2) CLOCK_MONOTONIC:从系统启动这一刻起开始计时,不受系统时间被用户改变的影响C

(3) LOCK_PROCESS_CPUTIME_ID:本进程到当前代码系统CPU花费的时间

(4) CLOCK_THREAD_CPUTIME_ID:本线程到当前代码系统CPU花费的时间

3. time

函数原型:

1
time_t time(time_t *t)

time函数的原型也可以理解为 long time(long *tloc),即返回一个long型整数。

time()函数获取当前的系统时间,返回的结果是一个time_t类型,其实就是一个大整数,其值表示从CUT(Coordinated Universal Time)时间1970年1月1日00:00:00(称为UNIX系统的Epoch时间)到当前时刻的秒数。

4. localtime

函数原型:

1
struct tm* localtime(struct tm*, time_t *t)

该函数常与time()函数搭配使用,将time_t所表示的CUT时间转换为本地时间(我们是+8区,比CUT多8个小时)并转成struct tm类型,该类型的各数据成员分别表示年月日时分秒。

用到的结构体

1
2
3
4
5
6
7
8
9
10
11
struct tm {
int tm_sec; /* 秒 – 取值区间为[0,59] */
int tm_min; /* 分 - 取值区间为[0,59] */
int tm_hour; /* 时 - 取值区间为[0,23] */
int tm_mday; /* 一个月中的日期 - 取值区间为[1,31] */
int tm_mon; /* 月份(从一月开始,0代表一月) - 取值区间为[0,11] */
int tm_year; /* 年份,其值等于实际年份减去1900 */
int tm_wday; /* 星期 – 取值区间为[0,6],其中0代表星期天,1代表星期一 */
int tm_yday; /* 从每年1月1日开始的天数– 取值区间[0,365],其中0代表1月1日 */
int tm_isdst; /* 夏令时标识符,夏令时tm_isdst为正;不实行夏令时tm_isdst为0 */
};

示例:

1
2
3
4
5
6
7
8
9
/* 获取所在地区的时间 */
void get_localtime()
{
time_t now ;
struct tm *tm_now ;
time(&now) ;
tm_now = localtime(&now) ;
printf("now datetime: %d-%d-%d %d:%d:%d\n", tm_now->tm_year+1900, tm_now->tm_mon+1, tm_now->tm_mday, tm_now->tm_hour, tm_now->tm_min, tm_now->tm_sec);
}

延时函数

1. sleep

函数原型:

1
unsigned int sleep(unsigned int seconds)

sleep()会令目前的进程暂停, 直到达到参数seconds 所指定的时间, 或是被信号所中断。该函数可以精确到秒级。

注意:
Windows下MFC中的Sleep()函数是精确到毫秒级。

2. usleep

函数原型:

1
void usleep(useconds_t usec)

该函数可以精确到微秒级。当sleep()的精确度满足不了需求时,可以采用usleep函数。

3. select

函数原型:

1
int select(int maxfdp1, fd_set *readset, fd_set *writeset, fd_set *exceptset,struct timeval *timeout)

select函数是我们在编写非阻塞程序时经常用到的一个函数。我们也可以使用select来做延时操作。

使用select函数,能实现微妙级别精度的定时器。实际测试中,是可以达到1ms精度的。

示例:

1
2
3
4
5
6
7
8
vois select_sleep(int sec, int msec)
{
struct timeval tv;
tv.tv_sec = sec;
tv.tv_usec = msec * 1000;

select(0, NULL, NULL, NULL, &tv);
}