加入收藏 | 设为首页 | 会员中心 | 我要投稿 云计算网_泰州站长网 (http://www.0523zz.com/)- 视觉智能、AI应用、CDN、行业物联网、智能数字人!
当前位置: 首页 > 站长学院 > PHP教程 > 正文

畅聊时间函数gettimeofday的成本

发布时间:2021-12-17 19:30:01 所属栏目:PHP教程 来源:互联网
导读:我们在程序中会频繁地取当前时间,例如处理一个http请求时,两次调用gettimeofday取差值计算出处理该请求消耗了多少秒。这样的调用无处不在,所以我们有必要详细了解下,gettimeofday这个函数做了些什么?内核1ms一次的时钟中断处理真的可以支持tv_usec字段

我们在程序中会频繁地取当前时间,例如处理一个http请求时,两次调用gettimeofday取差值计算出处理该请求消耗了多少秒。这样的调用无处不在,所以我们有必要详细了解下,gettimeofday这个函数做了些什么?内核1ms一次的时钟中断处理真的可以支持tv_usec字段达到微秒精度吗?它的调用成本在i386/x86_64体系架构上代价一样吗?如果在系统繁忙时,频繁的调用它有问题吗?
 
gettimeofday是C库提供的函数(不是系统调用),它封装了内核里的sys_gettimeofday系统调用,就是说,归根到底是系统调用。
 
但是,内核对于x86_64体系结构下,除了普通的系统调用外,还提供了sysenter和vsyscall方式来获取内核态的数据。目前我们使用的操作系统大都是x86_64体系的,如果我们用strace命令跟踪,就会发现gettimeofday命令实际上没有执行系统调用(i386体系会有),这是因为:x86_64体系上,使用vsyscall实现了gettimeofday这个系统调用。具体就是,创建了一个共享的内存页面,它是在内核态的,它的数据由内核来维护,但是,用户态也有权限访问这个内核页面,由此,不通过中断gettimeofday也就拿到了系统时间。
 
接下来,我来详细回答以上4个问题。
 
一、gettimeofday做了些什么?
 
它把内核保存的墙上时间和jiffies综合处理后返回给用户。解释下墙上时间和jiffies是什么:1、墙上时间就是实际时间(1970/1/1号以来的时间),它是由我们主板电池供电的(装过PC机的同学都了解)RTC单元存储的,这样即使机器断电了时间也不用重设。当操作系统启动时,会用这个RTC来初始化墙上时间,接着,内核会在一定精度内根据jiffies维护这个墙上时间。2、jiffies就是操作系统启动后经过的时间,它的单位是节拍数。有些体系架构,1个节拍数是10ms,但我们常用的x86体系下,1个节拍数是1ms。也就是说,jiffies这个全局变量存储了操作系统启动以来共经历了多少毫秒。我们来看看gettimeofday是如何做的。首先它调用了sys_gettimeofday系统调用。
 
[cpp]
asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __user *tz)  
{  
    if (likely(tv != NULL)) {  
        struct timeval ktv;  
        do_gettimeofday(&ktv);  
        if (copy_to_user(tv, &ktv, sizeof(ktv)))  
            return -EFAULT;  
    }  
    if (unlikely(tz != NULL)) {  
        if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))  
            return -EFAULT;  
    }  
    return 0;  
}  
大家看到,它调用do_gettimeofday函数取到当前时间存储到局部变量ktv上,www.linuxidc.com 然后调用copy_to_user把结果复制到用户空间。每个体系都有自己的实现,我这里就简单列下x86_64体系下do_gettimeofday的实现:
[cpp]
void do_gettimeofday(struct timeval *tv)  
{  
    unsigned long seq, t;  
    unsigned int sec, usec;  
  
    do {  
        seq = read_seqbegin(&xtime_lock);  
  
        sec = xtime.tv_sec;  
        usec = xtime.tv_nsec / 1000;  
  
        /* i386 does some correction here to keep the clock  
           monotonous even when ntpd is fixing drift.
           But they didn't work for me, there is a non monotonic
           clock anyways with ntp.
           I dropped all corrections now until a real solution can
           be found. Note when you fix it here you need to do the same
           in arch/x86_64/kernel/vsyscall.c and export all needed
           variables in vmlinux.lds. -AK */   
  
        t = (jiffies - wall_jiffies) * (1000000L / HZ) +  
            do_gettimeoffset();  
        usec += t;  
  
    } while (read_seqretry(&xtime_lock, seq));  
  
    tv->tv_sec = sec + usec / 1000000;  
    tv->tv_usec = usec % 1000000;  
}  
大家看到,只是把xtime加以jiffies修正后返回给用户而已。而xtime变量和jiffies的维护更新频率,就决定了时间精度,上面说了,每10或者1ms才处理一次时钟中断,难道精度只到1ms吗?继续往下。

(编辑:云计算网_泰州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读