上次講了alarm后,大致看了一下內核的時間表示,所以就記錄一下。
一、時間的表示方法:
Linux內核中表示時間的結構體和數據類型有5種:struct timeval; struct timespec; struct timezone; struct tm; time_t; struct rtc_time;
具體其聲明的頭文件在:include/linux/time.h
12 #ifndef _STRUCT_TIMESPEC 13 #define _STRUCT_TIMESPEC 14 struct timespec { 15 __kernel_time_t tv_sec; /* seconds */ 16 long tv_nsec; /* nanoseconds */ 17 }; 18 #endif
timespec由秒和納秒組成;精度要比timeval的要高,使用下列函數獲得:
184 extern void getnstimeofday(struct timespec *tv);
20 struct timeval { 21 __kernel_time_t tv_sec; /* seconds */ 22 __kernel_suseconds_t tv_usec; /* microseconds */ 23 }; 24
timeval由秒和微妙組成;使用下列函數獲得
extern void do_gettimeofday(struct timeval *tv);
25 struct timezone { 26 int tz_minuteswest; /* minutes west of Greenwich */ 27 int tz_dsttime; /* type of dst correction */ 28 }; 29
205 struct tm { 206 /* 207 * the number of seconds after the minute, normally in the range 208 * 0 to 59, but can be up to 60 to allow for leap seconds 209 */ 210 int tm_sec; 211 /* the number of minutes after the hour, in the range 0 to 59*/ 212 int tm_min; 213 /* the number of hours past midnight, in the range 0 to 23 */ 214 int tm_hour; 215 /* the day of the month, in the range 1 to 31 */ 216 int tm_mday; 217 /* the number of months since January, in the range 0 to 11 */ 218 int tm_mon; 219 /* the number of years since 1900 */ 220 long tm_year; 221 /* the number of days since Sunday, in the range 0 to 6 */ 222 int tm_wday; 223 /* the number of days since January 1, in the range 0 to 365 */ 224 int tm_yday; 225 };
tm是很直觀的表示時間的方法;
8 typedef __kernel_time_t time_t;
time_t該類型被定義在include/linux/types.h中,它是一個長整型,用來表示1970年以來的秒數。
並且在內核中定義了6中時鍾:
311 312 /* 313 * The IDs of the various system clocks (for POSIX.1b interval timers): 314 */ 315 #define CLOCK_REALTIME 0//表示系統當前時間,從1970年1.1日算起 316 #define CLOCK_MONOTONIC 1//系統的啟動時間,改時間是不會被改變的; 317 #define CLOCK_PROCESS_CPUTIME_ID 2 318 #define CLOCK_THREAD_CPUTIME_ID 3 319 #define CLOCK_MONOTONIC_RAW 4 320 #define CLOCK_REALTIME_COARSE 5 321 #define CLOCK_MONOTONIC_COARSE 6 322 #define CLOCK_BOOTTIME 7 323 #define CLOCK_REALTIME_ALARM 8 324 #define CLOCK_BOOTTIME_ALARM 9
二、有關時間操作:
上面簡單的介紹了表示內核時間的數據類型,接下來就是我們在實際中如何使用了。
首先介紹一個函數,該函數的作用是將秒轉換為格林時間;
48 /* 49 * Convert seconds since 01-01-1970 00:00:00 to Gregorian date. 50 */ 51 void rtc_time_to_tm(unsigned long time, struct rtc_time *tm) 52 { 53 unsigned int month, year; 54 int days; 55 56 days = time / 86400; 57 time -= (unsigned int) days * 86400; 58 59 /* day of the week, 1970-01-01 was a Thursday */ 60 tm->tm_wday = (days + 4) % 7; 61 62 year = 1970 + days / 365; 63 days -= (year - 1970) * 365 64 + LEAPS_THRU_END_OF(year - 1) 65 - LEAPS_THRU_END_OF(1970 - 1); 66 if (days < 0) { 67 year -= 1; 68 days += 365 + is_leap_year(year); 69 } 70 tm->tm_year = year - 1900; 71 tm->tm_yday = days + 1; 72 73 for (month = 0; month < 11; month++) { 74 int newdays; 75 76 newdays = days - rtc_month_days(month, year); 77 if (newdays < 0) 78 break; 79 days = newdays; 80 } 81 tm->tm_mon = month; 82 tm->tm_mday = days + 1; 83 84 tm->tm_hour = time / 3600; 85 time -= tm->tm_hour * 3600; 86 tm->tm_min = time / 60; 87 tm->tm_sec = time - tm->tm_min * 60; 88 89 tm->tm_isdst = 0; 90 } 91 EXPORT_SYMBOL(rtc_time_to_tm);
獲得當前系統的實際時間:
struct timespec ts;
struct rtc_time tm;
getnstimeofday(&ts);//獲取當前系統的秒;
rtc_time_to_tm(ts.tv_sec, &tm);//將系統的秒轉換為系統的格林時間;
pr_info("%d-%02d-%02d %02d:%02d:%02d\n",
tm.tm_year + 1900, tm.tm_mon +1, tm.tm_mday,
tm.tm_hour, tm.tm_min, tm.tm_sec);