1. 程式人生 > >linux時間型別localtime_r (轉載)

linux時間型別localtime_r (轉載)

linux時間型別localtime_r,struct tm *p

gettimeofday(&now ,NULL);取得當前時間的引數值,now可以是struct timespec 或者 struct timeval

型別的。
mktime函式原型:

定義函式
  time_t mktime(struct tm * timeptr);
函式說明
  mktime()用來將引數timeptr所指的tm結構資料轉換成從公元1970年1月1日0時0分0 秒算起至今的UTC時間所經過的秒數。
返回值
  返回經過的秒數。

localtime_r( time_t *t,struct tm *tm )函式功能與此相同,但是它可以將資料儲存到使用者提供的結構體中。是執行緒安全的,推薦使用它。它不需要設定tzname。

一、時間型別。
Linux下常用的時間型別有4個:time_t,struct timeval,struct timespec,struct tm。

gmtime() 函式將日曆時間timep轉換為用UTC時間表示的時間。它可能返回NULL,比如年份不能放到一個整數中。返回值指向一個靜態分配的結構,該結構可能會被接下來的任何日期和時間函式呼叫覆蓋。gmtime_r()函式功能與此相同,但是它可以將資料儲存到使用者提供的結構體中。
localtime() 函式將日曆時間timep轉換為使用者指定的時區的時間。這個函式的行為好像是它呼叫了tzset(3) 並且將外部變數tzname設定為當前時區的資訊,將timezone設為UTC和本地標準時間的差值,並且,如果在一年的部分時間使用日光節約規則時將daylight設定為非空值。返回值指向一個靜態分配的結構,該結構可能會被接下來的任何日期和時間函式呼叫覆蓋。localtime_r()函式功能與此相同,但是它可以將資料儲存到使用者提供的結構體中。它不需要設定tzname。
(1)time_t是一個長整型,一般用來表示用1970年以來的秒數。
(2)Struct timeval有兩個成員,一個是秒,一個是微妙。
struct timeval
{
long tv_sec;
long tv_usec;
};
(3)struct timespec有兩個成員,一個是秒,一個是納秒。
struct timespec
{
time_t tv_sec;
long tv_nsec;
};
(4)struct tm是直觀意義上的時間表示方法:
struct tm
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
};
二、 時間操作
(1) 時間格式間的轉換函式
主要是 time_t、struct tm、時間的字串格式之間的轉換。看下面的函式引數型別以及返回值型別:
char *asctime(const struct tm *tm);
char *ctime(const time_t *timep);
struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);
time_t mktime(struct tm *tm);
gmtime和localtime的引數以及返回值型別相同,區別是前者返回的格林威治標準時間,後者是當地時間。
(2) 獲取時間函式
兩個函式,獲取的時間型別看原型就知道了:
time_t time(time_t *t);
int gettimeofday(struct timeval *tv, struct timezone *tz);
前者獲取time_t型別,後者獲取struct timeval型別,因為型別的緣故,前者只能精確到秒,後者可以精確到微秒。
三、延時函式
主要的延遲函式有:sleep(),usleep(),nanosleep(),select(),pselect().
unsigned int sleep(unsigned int seconds);
void usleep(unsigned long usec);
int nanosleep(const struct timespec *req, struct timespec *rem);
int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,struct timeval *timeout);
int pselect(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, const struct timespec *timeout, const sigset_t *sigmask);

alarm函式是訊號方式的延遲,這種方式不直觀,這裡不說了。
僅通過函式原型中時間引數型別,可以猜測sleep可以精確到秒級,usleep/select可以精確到微妙級,nanosleep和pselect可以精確到納秒級。
而實際實現中,linux上的nanosleep和alarm相同,都是基於核心時鐘機制實現,受linux核心時鐘實現的影響,並不能達到納秒級的精度,man nanosleep也可以看到這個說明,man裡給出的精度是:Linux/i386上是10 ms ,Linux/Alpha上是1ms。
這裡有一篇文章http://blog.csdn.net/zhoujunyi/archive/2007/03/30/1546330.aspx

,測試了不同延遲函式之間的精確度。文章給出的結論是linux上精度最高的是select,10ms級別。我在本機器測試select和pselect相當,都達到了1ms級的精度,精度高於文章中給出的10ms,sleep在秒級以上和usleep/nanosleep相當。下面貼下我機器上1ms時候的測試結果,其他不貼了:
sleep 1000 0 -1000
usleep 1000 2974 1974
nanosleep 1000 2990 1990
select 1000 991 -9
pselect 1000 990 -10
gettimeofday 1000 1000 0
而使用gettimeofday迴圈不停檢測時間,可精確微秒級,不過不適宜用來做定時器模組。
因此後面的定時器模組將選擇select為延遲函式。

標頭檔案#include