上次讲了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);