歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> Linux技術 >> Linux下的時間

Linux下的時間

日期:2017/3/3 12:44:12   编辑:Linux技術

時鐘

硬件時鐘RTC(real time clock),記錄wall clock time,硬件對應到/dev/rtc設備文件,讀取設備文件可得到硬件時間

讀取方式

通過ioctl

#include <linux/rtc.h> 

int ioctl(fd, RTC_request, param);
hwclock命令

通常內核在boot以及從低電量中恢復時,會讀取RTC更新system time

軟件時鐘

HZ and jiffies, 由內核維護,對於PC通常HZ配置為 1s / 10ms = 100

精度影響select等依賴timeout的系統調用

HRT(high-resolution timers). Linux 2.6.21開始,內核支持高精度定時器,不受內核jiffy限制,可以達到硬件時鐘的精度。

外部時鐘

從網絡ntp,原子鐘等同步

時間

時間類別wall clock time => 硬件時間

real time => 從某個時間點(比如Epoch)開始的系統時間

sys and user time => 通常指程序在內核態和用戶態花的時間

時間的表示

time_t 從Epoch開始的秒數

calendar time 字符串

拆分時間 struct tm

struct tm { 

int tm_sec;         /* seconds */ 

int tm_min;         /* minutes */ 

int tm_hour;        /* hours */ 

int tm_mday;        /* day of the month */ 

int tm_mon;         /* month */ 

int tm_year;        /* year */ 

int tm_wday;        /* day of the week */ 

int tm_yday;        /* day in the year */ 

int tm_isdst;       /* daylight saving time */ 

};
struct timeval/struct timespec

[code]struct timeval {
  time_t seconds;
  suseconds_t useconds;
}

struct timespec {
  time_t   tv_sec;        /* seconds */
  long     tv_nsec;       /* nanoseconds */
};

系統時間的操作

[code]#include <time.h>
#include <sys/time.h>

// number of seconds since epoch
time_t time(time_t *t) 

//參數time_t*
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);

struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);

struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);

//參數struct tm*
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
time_t mktime(struct tm *tm);

int gettimeofday(struct timeval *tv, struct timezone *tz);//如果系統時間調整了會影響
int clock_gettime(clockid_t clk_id, struct timespec *tp);

//將tm按照format處理後放到s
size_t strftime(char *s, size_t max, const char *format, const struct tm *tm);

//將字符串時間s按照format格式化後放入tm
char *strptime(const char *s, const char *format, struct tm *tm);

定時器

sleep
[code]unsigned int sleep(unsigned int seconds);

usleep

[code]int usleep(useconds_t usec);
nanosleep

[code]int nanosleep(const struct timespec *req, struct timespec *rem);
alarm

[code]// SIGALARM after seconds
unsigned int alarm(unsigned int seconds);
timer_create

[code]int timer_create(clockid_t clockid, struct sigevent *sevp,
                        timer_t *timerid);
timerfd_create => 可以用select/poll/epoll監聽

[code]int timerfd_create(int clockid, int flags);
select

[code]// struct timeval可以精確到微秒(如果硬件有高精度時鐘支持)
int select(int nfds, fd_set *readfds, fd_set *writefds,
                  fd_set *exceptfds, struct timeval *timeout);
// struct timespec可以精確到納秒,但是pselect下次無法修改timeout 
int pselect(int nfds, fd_set *readfds, fd_set *writefds,
                   fd_set *exceptfds, const struct timespec *timeout,
                   const sigset_t *sigmask);

// 一般能提供周期,延時,時間點觸發,但核心還是時間點觸發的timer
// 1.call_period => 觸發一次重新注冊call_at
// 2.call_later => 轉換為call_at 
// 3.call_at => 時間點觸發的timer可以用一個優先級隊列保存
poll

[code]// timeout最小單位ms,並且rounded up to系統時鐘的精度
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
// 注意timespec會被轉換成ms
int ppoll(struct pollfd *fds, nfds_t nfds,
               const struct timespec *timeout_ts, const sigset_t *sigmask);
epoll

[code]// timeout最小單位ms,並且rounded up to系統時鐘的精度
int epoll_wait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout);
int epoll_pwait(int epfd, struct epoll_event *events,
                      int maxevents, int timeout,
                      const sigset_t *sigmask);

分布式系統的時間

扯點其他的東西:-)。時間是個復雜而有意思的東西,在單機上不同處理器不同進程不同線程可以讀到同一個系統時鐘CLOCK_REALTIME,而且在一定時間范圍內t1~t2發生的事件,即使在t1之前,t2之後系統時間與真實時間發生了一定偏移,只要時間戳的相對順序沒亂,那麼我們就可以完全確定t1~t2時間戳之間不同線程發生事件的順序。但是不同機器之間的系統時間總會互相漂移(ntp局域網0.1ms左右,互聯網1-50ms左右),導致我們沒法直接使用系統時間(google的原子鐘也是將一個時間段作為時間點的,只要這個時間段比較小,那麼性能應該可以接收),所以需要logic clock以及衍生出來的vector clock或者version number等。

沒有全局時鐘是分布式系統需要一致性算法的一個重要原因,因為我們沒辦法根據單機的系統時間戳來判斷多台機器之間事件的先後順序,那麼對於一個新的節點,我們要把之前所有的時間atomic broadcast到這個新節點就會出現問題,所以這也是分布式一致性算法(Paxos/Raft/Viewstamp Replication/Zab)解決的一個問題,當然再加上網絡的異步,以及無法獲知各個節點的全局狀態,以及機器crash等各種問題,這些算法往往加入了容錯性。

Copyright © Linux教程網 All Rights Reserved