1s ==1000ms == 1,000,000us == 1,000,000,000 nanosecond uname -a
Linux scott-Z170X 4.15.0-34-generic #37-Ubuntu SMP Mon Aug 27 15:21:48 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
intel i5-6500 我的CLOCKS_PER_SEC 是100W
---------------------------

//格式化输出
int64_t %ld , uint64_t %lu
longlong %lld , ulonglong %llu double %g
float %f
int %d
uint %u //指定输出到哪个地方,可以指定log文件 ,或者控制台 stdout
fprintf(stdout, "%g is %g\n", inputValue, outputValue);

Linux时钟精度:毫秒?微妙?纳秒?


首先:linux有一个很重要的概念——节拍,它的单位是(次/秒)。2.6内核这个值是1000,系统中用一个HZ的宏表征这个值。同时有全局的jiffies变量,表征从开机以来经过的节拍次数(这里面还有故事,后面说,先记住这个)。当然还有wall_jiffies的墙上jiffies来表示从 07-01-1970 到现在的节拍数。每个节拍里面执行一次时钟中断。就是说,它的精度是毫秒。 接着:内核中还有一个变量xtime表征系统的实际时间(墙上时间),定义如下。其中xtime.tv_sec以秒为单位,存放从Unix祖宗定的纪元时间(19700701)到现在的秒数。xtime.tv_nsec以纳秒为单位,记录从上一秒开始经过的纳秒数。就是说,它的精度是纳秒。 struct timespec xtime; struct timespec{
time_t tv_sec; //秒
long tv_nsec; //纳秒
}; 最后:linux提供一个gettimeofday的系统调用,它会返回一个timeval的结构体,定义如下。解释同上,tv_sec代表墙上时间的秒,tv_usec表示从上一秒到现在经过的微秒数。就是说,它的精度是微妙。 struct timeval{
long tv_sec; //秒
long tv_usec; //微妙
}; 精彩的来了:
1. 内核中的xtime会在每个时钟中断的时候被更新一次,也就是每个节拍更新一次。你妹!!每毫秒更新一次怎么能冒出来纳秒的精度??而且,内核还有可能丢失节拍。怎么能是纳秒??
2. 各种书上说,gettimeofday系统调用是读取的xtime的值。日,为啥读出来之后精度丢了?变成微妙了? 寻寻觅觅终于理清了故事:
针对问题1:在linux启动的时候,一个节拍的时间长度还会以纳秒为单位初始化到tick_nsec中,初始化值为999848ns,坑爹啊!不到一毫秒!节拍大约为1000.15Hz。靠!实际的节拍竟然不是准确的1000!所以在每个时钟中断通过wall_jiffies去更新xtime的时候得到的就是一个以纳秒为最小单位的的值。所以!xtime的粒度应该是不到1毫秒,也就是精度是不到1毫秒。 针对问题2:gettimeday系统调用的读xtime代码部分如下:
do{
unsigned long lost;
seq = read_seqbegin(&xtime_lock); usec = timer->get_offset(); //在计时器中取从上一次时钟中断到现在的微秒数
lost = jiffies - wall_jiffies;
if(lost)
usec += lost*(1000000/HZ); //HZ是节拍宏,值1000
sec = xtime.tv_sec;
usec += (xtime.tv_nsec/1000); //由纳秒转为微妙 }while(read_seqretry(&xtime_lock, seq)) while部分使用了seg锁,只看中间的就好了。加了注释之后就很清晰了。由于节拍可能会丢失,所以lost是丢失的节拍数(不会很多)。至于计时器就比较麻烦了,timer可能有下面四种情况。 a. 如果cur_timer指向timer_hpet对象,该方法使用HPET定时器——Inter与Microsoft开发的高精度定时器频率至少10MHz,也就是说此时可提供真正的微妙级精度。
b. 如果cur_timer指向timer_pmtmr对象,该方法使用ACPI PMT计时器(电源管理定时器)平率大约3.58MHz,也就是说也可以提供真正的微妙级精度。
c. 如果cur_timer指向timer_tsc对象,该方法使用时间戳计数器,内置在所有8086处理器,每个CPU时钟,计数器增加一次,频率就是CPU频率,所以timer精度最高。完全可以胜任微妙级的精度。
d. 如果cur_timer指向timer_pit对象,该方法使用PIT计数器,也即是最开始提到的节拍计数,频率大概是1000Hz,此时显然不能提供精度达到微妙的时间。所以只有这种情况是假毫秒精度! 综上:如果使用gettimeofday系统调用,只要不要使用节拍计数器就可以保证达到微妙精度的时间(刨除进程上下文时间误差)。至于网上说的可以拿到纳秒精度的时间,看起来都是错的。除非通过修改内核,使用时间戳计数器实现。Over! 最后最后说一个事情:jiffies的定义的是4字节,你可能猜想它初始值是0。实际上,事实并非如此!linux中jiffies被初始化为0xfffb6c20,它是一个32位有符号数,正好等于-300 000。因此,计数器会在系统启动5分钟内溢出。这是为了使对jiffies溢出处理有缺陷的内核代码在开发阶段被发现,避免此类问题出现在稳定版本中。 参考《深入理解linux内核》

#include <stdio.h> //file #include <iostream>
#include <ctime> //c++ 精确度s time(),ctime()
#include <string> #include <sys/time.h> //linux 精确度s, us gettimeofday() using namespace std; int main()
{
time_t beginTime,endTime;
struct timeval tvBegin,tvEnd;
struct timezone tz; time (&beginTime);
printf ("The current local time is: %s", ctime (&beginTime));
gettimeofday (&tvBegin , &tz); //do something time (&endTime);
printf ("The current local time is: %s \n", ctime (&endTime));
gettimeofday (&tvEnd , &tz); //tv_sec 是 Unix timestamp
//tvEnd.tv_sec-tvBegin.tv_sec 得到多少s, ==>1 s*1000 (5-3=2, 2*1000=>2000ms)
//tvEnd.tv_usec-tvBegin.tv_usec 得到多少us,==>1 us/1000 (55100-373988= -31812, 2/1000=>318ms)
//2000ms+(-318ms) 就是最终消耗的时间 1682ms uint64_t uSpendms = (tvEnd.tv_sec-tvBegin.tv_sec)*1000+(tvEnd.tv_usec-tvBegin.tv_usec)/1000; #ifdef TEST
printf ("uSpendms = %lu .tvEnd.tv_sec = %ld, tvBegin.tv_sec=%ld ; tvEnd.tv_usec = %ld, tvBegin.tv_usec=%ld .\n",
uSpendms,
tvEnd.tv_sec, tvBegin.tv_sec,
tvEnd.tv_usec, tvBegin.tv_usec);
#else
std::cout<< "tvEnd.tv_sec ="<<tvEnd.tv_sec << ". tvBegin.tv_sec ="<<tvBegin.tv_sec <<std::endl;
std::cout<< "tvEnd.tv_usec ="<<tvEnd.tv_usec << ". tvBegin.tv_usec ="<<tvBegin.tv_usec <<std::endl;
std::cout<< "SpendTime="<<uSpendms<<"ms"<<std::endl; #endif #ifdef WRITE_LOG int i;
double result; // open the output file
FILE* fout = fopen(“test.log”, "w");
if (!fout) {
return 1;
} // create a source file with a table of square roots
fprintf(fout, "double sqrtTable[] = {\n");
for (i = 0; i < 10; ++i) {
result = sqrt(static_cast<double>(i));
fprintf(fout, "%g,\n", result);
} // close the table with a zero
fprintf(fout, "0};\n");
fclose(fout); #endif return 0; }

linux 时间处理 + 简单写log的更多相关文章

  1. Linux 时间以及时间间隔的简单处理.

    最近想知道自己的一个部署脚本的耗时, 中午时间看了一下最简单的Linux 时间函数的处理 我这里的处理非常简单, 仅仅是够用而已. 处理过程. 1. 获取当前时间: time1=`date` 或者是 ...

  2. Linux下一个简单的日志系统的设计及其C代码实现

    1.概述 在大型软件系统中,为了监测软件运行状况及排查软件故障,一般都会要求软件程序在运行的过程中产生日志文件.在日志文件中存放程序流程中的一些重要信息, 包括:变量名称及其值.消息结构定义.函数返回 ...

  3. Linux时间设置与iptables命令

    日期与时间设置 timedatectl:显示目前时区与时间等信息 [root@localhost zhang]# timedatectl Local time: Thu 2018-01-18 10:1 ...

  4. Linux守护进程简单介绍和实例具体解释

    Linux守护进程简单介绍和实例具体解释 简单介绍 守护进程(Daemon)是执行在后台的一种特殊进程.它独立于控制终端而且周期性地执行某种任务或等待处理某些发生的事件.守护进程是一种非常实用的进程. ...

  5. 模块(二)——简单的log日志

    简单的log日志 鉴于任何功能模块或系统在调试时都需要日志打印,这里随便写了一下,作为以后代码调试之用,只实现了不同等级的日志输出功能,其他的调试功能以后再行添加:使用方法简单,只需要在头文件里事先按 ...

  6. 关于Quartz.NET作业调度框架的一点小小的封装,实现伪AOP写LOG功能

    Quartz.NET是一个非常强大的作业调度框架,适用于各种定时执行的业务处理等,类似于WINDOWS自带的任务计划程序,其中运用Cron表达式来实现各种定时触发条件是我认为最为惊喜的地方. Quar ...

  7. 基于.Net Framework 4.0 Web API开发(3):ASP.NET Web APIs 异常的统一处理Attribute 和统一写Log 的Attribute的实现

    概述:  ASP.NET Web API 的好用使用过的都知道,没有复杂的配置文件,一个简单的ApiController加上需要的Action就能工作.但是项目,总有异常发生,本节就来谈谈API的异常 ...

  8. Linux curl使用简单介绍

    在两台新搬迁的微信服务器上执行命令: curl -H "Content-Type: application/json" -d '{"partner_no":&q ...

  9. Linux时间子系统之(十五):clocksource

    专题文档汇总目录 Notes:clocksource基本概念,struct clocksource详解:注册和注销clocksource:内核如何选取clocksource:clocksource相关 ...

随机推荐

  1. Gradle-jar-aar

    Ref:Android Studio系列教程 Ref:Android Studio系列教程四--Gradle基础 Ref:Intellij IDEA 14.x 中的Facets和Artifacts的区 ...

  2. webdriver与JS操作浏览器元素

    1.JQuery的选择器实例 语法 描述 $(this) 当前 HTML 元素 $("p") 所有 <p> 元素 $("p.intro") 所有 c ...

  3. myBatis中使用Map进行遍历

    myBatis中使用Map获取key, value的方式 第一次的配置 <trim prefix=" tags =case" suffix="end"&g ...

  4. pycharm ctrl+滚轮调节字体大小

    File --> Setting --> Editor --> General --> 勾选Change font size (zoom) with Ctrl+Mouse Wh ...

  5. 牛客小白月赛1 G あなたの蛙は旅⽴っています【DP】

    题目链接 https://www.nowcoder.com/acm/contest/85/G 思路 按照题解上的方式 存取数据 然后DP一下 就可以了 AC代码 #include <cstdio ...

  6. 让你快速上手Runtime(转)

    前言 本篇主要介绍Runtime在开发中的一些使用场景,顺便讲解了下MJExtension的底层实现.如果喜欢我的文章,可以关注我微博:袁峥Seemygo,也可以来小码哥,了解下我们的iOS培训课程. ...

  7. case 练习

    #!/bin/bash RED_COLOR="\E[1;31m" GREEN_COLOR="\E[1;32m" YELLOW_COLOR="\E[1; ...

  8. POJ1182 食物链 并查集

    #include<iostream>#include<stdio.h>#include<string.h>using namespace std;const int ...

  9. 算法(Algorithms)第4版 练习 2.2.23

    测试结果: 算法(Algorithms)第4版 练习 2.2.10 算法(Algorithms)第4版 练习 2.2.11(1) 算法(Algorithms)第4版 练习 2.2.11(2) 算法(A ...

  10. eclipse从Git获取项目更新

    1.项目上右键 ——> Team ——> pull   如果报错:   解决方法:   依次打开:Window ——> Preferences ——> Team ——> ...