实际时间

 

  当前实际时间(墙上时间)

  1. 在<Time.h(incluce/linux)>中 
  2. extern struct timespec xtime; 
  3. #ifndef _STRUCT_TIMESPEC 
  4. #define _STRUCT_TIMESPEC 
  5. struct timespec { 
  6.     time_t  tv_sec;     /* seconds */ 
  7.     long    tv_nsec;    /* nanoseconds 十亿分之一秒*/ 
  8. }; 
  9. #endif

  xtime.tv_sec以秒为单位,存放着自1970年7月1日(UTC)以来经过的时间,1970年1月1日被称为纪元。多数Unix系统的墙上时间都是基于该纪元而言的。xtime.tv_nsec记录自上一秒开始经过的纳秒数。

  读写xtime变量需要使用xtime_lock锁,该锁是一个seqlock锁。

  更新xtime首先要申请一个seqlock锁:

  

  1. write_seqlock(&xtime_lock);
  2.   ……
  3. /*update xtime*/
  4.   ……
  5. write_sequnlock(&xtime_lock);

  读取xtime时也要使用read_seqbegin()函数和read_seqtry()函数:

  1. do{
  2. unsigned long lost;
  3. seq=read_seqbegin(&xtime_lock);
  4. usec=timer->get_offset();
  5. lost=jiffies-wall_jiffies;
  6. if(lost)
  7.    usec+=lost*(1000000/HZ);
  8. sec=xtime.tv_sec;
  9. usec+=(xtime.tv_nsec/1000);
  10. }while(read_seqretry(&xtime_lock,seq))

 

  该循环不断重复,直到读者确认读取数据时没有写操作介入。如果发现循环期间有时钟中断处理程序更新xtime,那么read_seqtry()函数就返回无效序列号,继续循环等待。

  从用户空间取得墙上时间的主要接口是gettimeofday(),在内核中对应的系统调用为sys_gettimeofday():

  1. 在<Time.c(kernel)>中
  2. asmlinkage long sys_gettimeofday(struct timeval __user *tv, struct timezone __user *tz)
  3. {
  4.     if (likely(tv != NULL)) {
  5.         struct timeval ktv;
  6.         do_gettimeofday(&ktv);
  7.         if (copy_to_user(tv, &ktv, sizeof(ktv)))
  8.             return -EFAULT;
  9.     }
  10.     if (unlikely(tz != NULL)) {
  11.         if (copy_to_user(tz, &sys_tz, sizeof(sys_tz)))//把系统时区sys_tz返回用户
  12.             return -EFAULT;
  13.     }
  14.     return 0;
  15. }
  16. //该函数与体系结构相关
  17. void do_gettimeofday (struct timeval *tv)
  18. {
  19.     unsigned long seq, nsec, usec, sec, offset;
  20.     //循环读取xtime
  21.     do {
  22.         seq = read_seqbegin(&xtime_lock);
  23.         offset = time_interpolator_get_offset();
  24.         sec = xtime.tv_sec;
  25.         nsec = xtime.tv_nsec;
  26.     } while (unlikely(read_seqretry(&xtime_lock, seq)));
  27.     usec = (nsec + offset) / 1000;
  28.     while (unlikely(usec >= USEC_PER_SEC)) {
  29.         usec -= USEC_PER_SEC;
  30.         ++sec;
  31.     }
  32.     tv->tv_sec = sec;
  33.     tv->tv_usec = usec;
  34. }
  35. #ifdef CONFIG_TIME_INTERPOLATION
  36. void getnstimeofday (struct timespec *tv)
  37. {
  38.     unsigned long seq,sec,nsec;
  39.     do {
  40.         seq = read_seqbegin(&xtime_lock);
  41.         sec = xtime.tv_sec;
  42.         nsec = xtime.tv_nsec+time_interpolator_get_offset();
  43.     } while (unlikely(read_seqretry(&xtime_lock, seq)));
  44.     while (unlikely(nsec >= NSEC_PER_SEC)) {
  45.         nsec -= NSEC_PER_SEC;
  46.         ++sec;
  47.     }
  48.     tv->tv_sec = sec;
  49.     tv->tv_nsec = nsec;
  50. }
  51. #else
  52. #ifndef CONFIG_GENERIC_TIME
  53. /*
  54.  * Simulate gettimeofday using do_gettimeofday which only allows a timeval
  55.  * and therefore only yields usec accuracy
  56.  */
  57. void getnstimeofday(struct timespec *tv)
  58. {
  59.     struct timeval x;
  60.     do_gettimeofday(&x);
  61.     tv->tv_sec = x.tv_sec;
  62.     tv->tv_nsec = x.tv_usec * NSEC_PER_USEC;
  63. }

 

  1. 在<Time.h(include/linux)>中
  2. struct timeval {
  3.     time_t      tv_sec;     /* seconds */
  4.     suseconds_t tv_usec;    /* microseconds */
  5. };
  6. struct timezone {
  7.     int tz_minuteswest; /* minutes west of Greenwich */
  8.     int tz_dsttime; /* type of dst correction */
  9. };

  虽然内核也实现了time()系统调用,但是gettimeofday()几乎完全取代了它。C库函数也提供了墙上时间相关的库调用,比如ftime(),ctime()。

  除了更新xtime时间外,内核不会想用户空间程序那样频繁的使用xtime。但是,在文件系统的实现代码中存放访问时间戳(创建,存取,修改等)需要使用xtime。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值