Linux获取系统信息
1.Linux中的时间
1.1GMT时间和UTC时间、定时器和实时时钟
1.2 jiffies详解
1.3Linux中和时间相关的API
2.获取随机数
1.Linux中的时间
1.1GMT时间和UTC时间、定时器和实时时钟
GMT时间和UTC时间:
GMT时间是指位于伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。用格林尼治的当地时间作为全球国际时间,用以描述全球性的事件的时间。
GMT时间是以前使用的,近些年来越来越多的使用UTC时间。协调世界时(UTC) 是世界统一时间,世界标准时间国际协调时间, 协调世界时,又称世界统一时间,世界标准时间,
UTC+(+0800)=北京时间
定时器和实时时钟:
定时器(timer)定的时间就是段时间。
实时时钟(RTC)和点时间有关。
1.2 jiffies详解
jiffies是linux内核中的一个全局变量,这个变量用来记录以内核的节拍时间为单位时间长度的一个数值。内核配置的时候定义了一个节拍时间,实际上linux内核的调度系统工作时就是以这个节拍时间为时间片的。jiffies变量开机时有一个基准值,内核每过一个节拍时间jiffies就会加1,然后到了系统的任意一个时间我们当前时间就被jiffies这个变量所标注。
内核在开机启动的时候会读取RTC硬件获取一个初始基准时间,这个基准时间对应一个jiffies值(基准时间换算成jiffies值的方法是:用这个时间减去1970-01-01 00:00:00 +0000(UTC),然后把这个时间段换算成jiffies数值),这个jiffies值作为开机时的基准jiffies值存在。然后系统运行时每个时钟节拍的末尾都会给jiffies这个全局变量加1,操作系统就使用jiffies这个全局变量记录了下来当前的时间。当我们需要当前时间点时,就用jiffies这个时间点去计算(计算方法就是先把这个jiffies值对应的时间段算出来,然后加上1970-01-01 00:00:00 +0000(UTC))。
操作系统只在开机时读一次RTC,整个系统运行过程中RTC是无作用的。RTC的真正作用其实是在系统的2次开机之间进行时间的保存。jiffies这个变量记录的其实是段时间(其实就是当前时间和1970-01-01 00:00:00 +0000(UTC)这个时间的差值)。
一个节拍的时间取决于操作系统的配置,现代Linux系统一般是10ms或者1ms。这个时间其实就是调度时间,在内核中用HZ来记录和表示。如果HZ定义成1000难么时钟节拍就是1/HZ,也就是1ms。
1.3Linux中和时间相关的API
time:
#include
time_t time(time_t *tloc);
time系统调用返回当前时间以秒为单位的距离1970-01-01 00:00:00 +0000(UTC)过去的秒数。这个time内部就是用jiffies换算得到的秒数。其他函数基本都是围绕着time来工作的。
ctime:
#include
char *ctime(const time_t *timep);
ctime是C库函数,它可以从time_t出发得到一个容易观察的字符串格式的当前时间。
gmtime、localtime和mktime:
#include
struct tm *gmtime(const time_t *timep);
struct tm *localtime(const time_t *timep);
time_t mktime(struct tm *tm);
struct tm:
struct tm {
int tm_sec; /* Seconds (0-60) */
int tm_min; /* Minutes (0-59) */
int tm_hour; /* Hours (0-23) */
int tm_mday; /* Day of the month (1-31) */
int tm_mon; /* Month (0-11) */
int tm_year; /* Year - 1900 */
int tm_wday; /* Day of the week (0-6, Sunday = 0) */
int tm_yday; /* Day in the year (0-365, 1 Jan = 0) */
int tm_isdst; /* Daylight saving time */
};
gmtime和localtime会把time得到的秒数变成一个struct tm结构体表示的时间。区别是gmtime得到的是国际时间,而localtime得到的本地时间。mktime用来完成相反方向的转换(struct tm–>time_t)。
asctime和strftime:
#include
char *asctime(const struct tm *tm);
size_t strftime(char *s, size_t max, const char *format,const struct tm *tm);
如果从struct tm出发想得到字符串格式的时间,asctime或者strftime都可以。
gettimeofday和settimeofday:
#include
int gettimeofday(struct timeval *tv, struct timezone *tz);
int settimeofday(const struct timeval *tv, const struct timezone *tz);
struct timeval和struct timezone:
struct timeval {
time_t tv_sec; /* seconds */
suseconds_t tv_usec; /* microseconds */
};
struct timezone {
int tz_minuteswest; /* minutes west of Greenwich */
int tz_dsttime; /* type of DST correction */
};
gettimeofday返回的时间是由struct timeval和struct timezone这两个结构体来共同表示的,其中timeval表示时间,而timezone表示时区。settimeofday是用来设置当前的时间和时区的。
总结:不管用哪个系统调用,最终得到的时间本质上都是一个时间(这个时间最终都是从kernel中记录的jiffies中计算得来的),只不过不同的函数返回的时间的格式不同,精度不同。
3.3.3.3、gmtime和localtime
(1)gmtime获取的时间中:年份是以1970为基准的差值,月份是0表示1月,小时数是以UTC时间的0时区为标准的小时数(北京是东8区,因此北京时间比这个时间大8)
(2)猜测localtime和gmtime的唯一区别就是localtime以当前计算机中设置的时区为小时的时间基准,其余一样。实践证明我们的猜测是正确的。
2.获取随机数
随机数是随机出现,没有任何规律的一组数列。真正的完全随机的数列是不存在的,只是一种理想情况,一般只能通过一些算法得到一个伪随机数序列。
rand()函数和srand()函数:
#include
int rand(void);
void srand(unsigned int seed);
单纯使用rand每次执行程序得到的伪随机序列是同一个序列,没法得到其他序列,因为rand内部的算法是通过一个种子(seed,一个int类型的原始参数,默认为1),作为seed的,种子一定则算法也是一定的,所以每次得到的伪随机序列是同一个。
因此要想每次执行这个程序获取的伪随机序列不同,则每次都要给不同的种子。srand函数就是用来设置随机种子的。
随机数示例(获取长度为10,大小为0-5之间的随机序列):
#include
#include
int main(int argc, char **argv)
{
int val = 0;
srand(time(NULL));
for (int i=0; i<10; i++)
{
val = rand();
printf("%d ", (val % 6));
}
printf("\n");
return 0;
}
output:
5 2 1 3 0 5 2 1 2 4
总结:在每次执行程序时,先用srand设置一个不同的种子,然后再多次调用rand获取一个伪随机序列,这样就可以每次都得到一个不同的伪随机序列(一般做法是用time函数的返回值来做srand的参数)。