Linux系统时间

Linux系统时间有两种:

  • 日历时间。该值是自协调世界时(UTC)1970年1月1日00:00:00这个特定时间以来经过的秒数累计值。基本数据类型用time_t保存,实际就是uint64_t类型。
  • 进程时间。也被称为CPU时间,用于度量进程使用的中央处理器资源。进程时间以时钟滴答计算。

测试`Linux` 指令,查看 `Markdown` 语法是否正确

时间戳的获取

time()

#include <time.h>
time_t time(time_t *calptr);
/* time()函数只能得到秒精度的时间 */

time返回当前时间的时间戳,也就是从世界时(1970年1月1日)到现在的秒数;calptr不为空时,时间戳也会写入到该指针中.

#include <stdio.h>
#include <time.h>

int main()
{
    time_t timep;
    time(&timep);
    /* 或者使用
     timep = time(NULL);
    */
   printf("当前时间戳:%ld",timep);

}

gettimeofday() 和clock_gettime()

#include <sys/time.h>
int gettimeofday(struct timeval *tp, void *tzp);
//由于历史的原因,tzp的唯一合法值是NULL

 int clock_gettime(clockid_t clock_id, struct timespec *tsp);
//clock_id有多个选择,当选择为CLOCK_REALTIME时与time的功能相似,但是时间精度更高。

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

struct timespec
{
    time tv_sec;    /* 秒 */
    long tv_nsec;   /* 纳秒 */
};

例如:

#include <time.h>
#include <sys/time.h> 
#include <iostream >
#include <stdlib.h >

using namespace std;

int main()
{
time_t dwCurTime1;
dwCurTime1 = time(NULL);

struct timeval stCurTime2;
gettimeofday(&stCurTime2, NULL);

struct timespec stCurTime3;
clock_gettime(CLOCK_REALTIME, &stCurTime3);

cout << "Time1: " << dwCurTime1 << "s" << endl;
cout << "Time2: " << stCurTime2.tv_sec << "s, " << stCurTime2.tv_usec << "us" << endl;
cout << "Time3: " << stCurTime3.tv_sec << "s, " << stCurTime3.tv_nsec << "ns" << endl;

return 0;
}

结果:

编译时要在编译命令最后加上-lrt链接Real Time动态库,如
 g++ -o time2 test_time_linux_2.cpp -lrt
 Time1: 1533289490s
 Time2: 1533289490s, 133547us
 Time3: 1533289490s, 133550060ns

asctime

#include <time.h>
char *asctime(const struct tm* timeptr);

将结构中的信息转化为真实世界的时间,以字符串的形式显示

ctime

char *ctime(const time_t *time);

将timep转化为真实世界的时间,以字符串显示,它和asctime不同在于传入的参数形式不同

difftime

double difftime(time_t time1, time_t time2);

返回两个时间相差的秒数

gettimeofday

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

返回当前距离1970年的秒数和微妙数,后面的tz是时区,一般不用

mktime

time_t mktime(struct tm* timeptr);

将struct tm结构的时间转化为从1970年至今的秒数

可视化时间

tm结构体

得到的时间戳不能直观的显示现在的时间,需要使用tm 结构体来表示我们日常使用的时间,该结构体定义如下:

struct tm
{
int tm_sec; /*秒,正常范围0-59, 但允许至61*/
int tm_min; /*分钟,0-59*/
int tm_hour; /*小时, 0-23*/
int tm_mday; /*日,即一个月中的第几天,1-31*/
int tm_mon; /*月, 从一月算起,0-11*/ 1+p- tm_mon;
int tm_year; /*年, 从1900至今已经多少年*/ 1900+ p- tm_year;
int tm_wday; /*星期,一周中的第几天, 从星期日算起,0-6*/
int tm_yday; /*从今年1月1日到目前的天数,范围0-365*/
int tm_isdst; /*日光节约时间的旗标*/
};

time_t转成tm

gmtime和localtime可以将time_t类型的时间戳转为tm结构体

struct tm* gmtime(const time_t *timep);
//将time_t表示的时间转化为没有经过时区转化的UTC时间,是一个struct tm结构指针

struct tm* localtime(const time_t *timep);
//和gmtime功能类似,但是它是经过时区转换的时间,也就是可以转化为北京时间

灵活安全的时间转换函数strftime()

/*
 * @buf:存储输出的时间
 * @maxsize:缓存区的最大字节长度
 * @format:指定输出时间的格式
 * @tmptr:指向结构体tm的指针
*/
size_t strftime(char* buf, size_t maxsize, const char* format, const struct tm *tmptr);

format格式:

 %a 星期几的简写
 %A 星期几的全称
 %b 月分的简写
 %B 月份的全称
 %c 标准的日期的时间串
 %C 年份的后两位数字
 %d 十进制表示的每月的第几天
 %D 月/天/年
 %e 在两字符域中,十进制表示的每月的第几天
 %F 年-月-日
 %g 年份的后两位数字,使用基于周的年
 %G 年分,使用基于周的年
 %h 简写的月份名
 %H 24小时制的小时
 %I 12小时制的小时
 %j 十进制表示的每年的第几天
 %m 十进制表示的月份
 %M 十时制表示的分钟数
 %n 新行符
 %p 本地的AM或PM的等价显示
 %r 12小时的时间
 %R 显示小时和分钟:hh:mm
 %S 十进制的秒数
 %t 水平制表符
 %T 显示时分秒:hh:mm:ss
 %u 每周的第几天,星期一为第一天 (值从0到6,星期一为0)
 %U 第年的第几周,把星期日做为第一天(值从0到53)
 %V 每年的第几周,使用基于周的年
 %w 十进制表示的星期几(值从0到6,星期天为0)
 %W 每年的第几周,把星期一做为第一天(值从0到53)
 %x 标准的日期串
 %X 标准的时间串
 %y 不带世纪的十进制年份(值从0到99)
 %Y 带世纪部分的十制年份
 %z,%Z 时区名称,如果不能得到时区名称则返回空字符。
 %% 百分号

例如:

#include <time.h 
#include <sys/time.h 
#include <iostream 
#include <stdlib.h 

using namespace std;

int main()
{
time_t dwCurTime1;
dwCurTime1 = time(NULL);

struct tm* pTime;
pTime = localtime(&dwCurTime1);

char buf[100];

strftime(buf, 100, "time: %r, %a %b %d, %Y", pTime);

cout << buf << endl;

return 0;
}

结果:

 time: 08:18:12 PM, Fri Aug 03, 2018

时间函数之间的关系图

进程时间

进程时间是进程被创建后使用CPU的时间,进程时间被分为两个部分:

  • 用户CPU时间:在用户模式下使用CPU时间
  • 内核CPU时间:在内核态模式下使用CPU的时间,这是执行内核调用或者其它特殊任务所需的时间

clock函数

clock函数提供了一个简单的接口用于取得进程时间,它返回一个值描述进程使用的总的CPU时间(包括用户时间和内核时间),clock函数定义如下:

#include &lt;time.h&gt;
clock_t clock(void);
//if error,return -1

clock函数返回值的计量单位是 CLOCKS_PER_SEC ,将返回值除以这个计量单位就得到了进程时间的秒数

times函数

times函数也是一个进程时间函数,有更加具体的进程时间表示,函数定义如下:

#include &lt;sys/time.h&gt;
clock_t times(struct tms *buf);

struct tms{
    clock_t tms_utime;
    clock_t tms_stime;
    clock_t tms_cutime;
    clock_t tms_cstime;
};

times函数虽然返回值类型还是clock_t,但是与clock函数返回值的计量单位不同。times函数的返回值的计量单位要通过sysconf(SC_CLK_TCK)来获得

Linux系统编程手册上一个完整案例:

#include &lt;time.h 
#include &lt;sys/times.h 
#include &lt;unistd.h 
#include &lt;stdio.h 

static void displayProcessTime(const char* msg)
{
struct tms t;
clock_t clockTime;
static long clockTick = 0;

if (msg != NULL) 
{
printf(&quot;%sn&quot;, msg);
}

if (clockTick == 0)
{
clockTick = sysconf(_SC_CLK_TCK);
if (clockTick &lt; 0) return;
}

clockTime = clock();
printf(&quot;clock return %ld CLOCKS_PER_SEC (%.2f seconds)n&quot;, (long)clockTime, (double)clockTime/CLOCKS_PER_SEC);

times(&amp;t);
printf(&quot;times return user CPU = %.2f; system CPU = %.2fn&quot;, (double)t.tms_utime / clockTick, (double)t.tms_stime / clockTick);
}

int main()
{
printf(&quot;CLOCKS_PER_SEC = %ld, sysconf(_SC_CLK_TCK) = %ldn&quot;, (long)CLOCKS_PER_SEC, sysconf(_SC_CLK_TCK));

displayProcessTime(&quot;start:&quot;);
for (int i = 0; i &lt; 1000000000; ++i)
{
getpid();
}
printf(&quot;n&quot;);
displayProcessTime(&quot;end:&quot;);

return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *