获取Linux系统信息
一、常用的时间相关的API和C库函数:
time
time_ttime(time_t *t);
time(&tNow);
time系统调用返回当前时间以秒为单位的距离1970-01-01 00:00:00 +0000(UTC)过去的秒数。这个time内部就是用jiffies换算得到的秒数。
/*****************************************************************************/
gmtime
structtm *gmtime(const time_t *timep);
struct tm*gmtime_r(const time_t *timep, struct tm *result);
gmtime_r(&tNow, &tmNow);
localtime
structtm *localtime(const time_t *timep);
struct tm*localtime_r(const time_t *timep, struct tm *result);
localtime_r(&tNow, &tmNow);
mktime
time_tmktime(struct tm *tm);
time得到的秒数变成一个struct tm结构体表示的时间。区别是gmtime得到的是国际时间,而localtime得到的是本地时间。mktime用来完成相反方向的转换(struct tm到time_t)
/*****************************************************************************/
/****************************************************************************/
asctime
char*asctime(const struct tm *tm);
char*asctime_r(const struct tm *tm, char *buf);
asctime_r(&tmNow, buf);
strftime
size_tstrftime(char *s, size_t max, const char *format, const struct tm *tm);
ret = strftime(buf, sizeof(buf), "%Y-%m-%d. %H-%M-%S",&tmNow);
ctime
char*ctime(const time_t *timep);
char*ctime_r(const time_t *timep, char *buf);
ctime(&tNow)
如果从struct tm出发想得到字符串格式的时间,可以用asctime或者strftime都可以。(如果从time_t出发想得到字符串格式的时间用ctime即可)
/****************************************************************************/
gettimeofday:
intgettimeofday(struct timeval *tv, struct timezone *tz);
ret = gettimeofday(&tv,&tz);
settimeofday:
gettimeofday返回的时间是由struct timeval和struct timezone这两个结构体来共同表示的,其中timeval表示时间,而timezone表示时区。settimeofday是用来设置当前的时间和时区的。
/*****************************************************************************/
linux中随机数相关API
(1) 连续多次调用rand函数可以返回一个伪随机数序列int rand_r(unsigned int *seedp);
RAND_MAX:2147483647
(2) srand函数用来设置rand获取的伪随机序列 void srand(unsigned int seed);
srand(atoi(argv[1]));自定义seed
srand(time(NULL));将系统时间作为seed,1mstime值改变一次,伪随机程度较高
二、系统时间具体分析:
(0). Linux中的系统时间jiffies
a>. Jiffies(系统基准时间)变量开机时有一个基准值,然后内核每过一个节拍时间jiffies就会加1,然后到了系统的任意一个时间我们当前时间就被jiffies这个变量所标注。
b>. jiffies这个变量记录的其实是段时间(其实就是当前时间和1970-01-0100:00:00 +0000(UTC)这个时间的差值)
(1).时间相关API的区别:
(1). time
time能得到一个当前时间距离标准起点时间1970-01-0100:00:00 +0000(UTC)过去了多少秒
(2). ctime
(1)ctime可以从time_t出发得到一个容易观察的字符串格式的当前时间。
(2)ctime好处是很简单好用,可以直接得到当前时间的字符串格式,直接打印来看。坏处是ctime的打印时间格式是固定的,没法按照我们的想法去变。
(3)实验结果可以看出ctime函数得到的时间是考虑了计算机中的本地时间的(计算机中的时区设置)
(3). gmtime和localtime
(1)gmtime获取的时间中:年份是以1970为基准的差值,月份是0表示1月,小时数是以UTC时间的0时区为标准的小时数(北京是东8区,因此北京时间比这个时间大8)
(2)猜测localtime和gmtime的唯一区别就是localtime以当前计算机中设置的时区为小时的时间基准,其余一样。实践证明我们的猜测是正确的。
(4). mktime
(1)从OS中读取时间时用不到mktime的,这个mktime是用来向操作系统设置时间时用的。
(5). asctime
(1)asctime得到一个固定格式的字符串格式的当前时间,效果上和ctime一样的。区别是ctime从time_t出发,而asctime从structtm出发。
(6). strftime
(1)asctime和ctime得到的时间字符串都是固定格式的,没法用户自定义格式
(2)如果需要用户自定义时间的格式,则需要用strftime。
(7). gettimeofday和settimeofday
(1)前面讲到的基于time函数的那个系列都是以秒为单位来获取时间的,没有比秒更精确的时间。
(2)有时候我们程序希望得到非常精确的时间(譬如以us为单位),这时候就只能通过gettimeofday来实现了。
三、proc文件系统的使用
1、 cat以手工查看
常用proc中的文件介绍
(1)/proc/cmdline
(2)/proc/cpuinfo
(3)/proc/devices
(4)/proc/interrupts
2、程序中可以文件IO访问
3、在shell程序中用cat命令结合正则表达式来获取并处理内核信息
4、proc文件系统 & sys文件系统:
proc虚拟文件系统的工作原理
(1)linux内核是一个非常庞大、非常复杂的一个单独的程序,对于这样的一个程序来说调试是非常复杂的。
(2)项kernel这样庞大的项目,给里面添加/更改一个功能是非常麻烦的,因为你这添加的一个功能可能会影响其他已经有的。
(3)早期内核版本中尽管调试很麻烦,但是高手们还可以凭借个人超凡脱俗的能力去驾驭。但是到了2.4左右的版本的时候,这个难度已经非常大了。
(4)为了降低内核调试和学习的难度,内核开发者们在内核中添加了一些属性专门用于调试内核,proc文件系统就是一个尝试。
(5)proc文件系统的思路是:在内核中构建一个虚拟文件系统/proc,内核运行时将内核中一些关键的数据结构以文件的方式呈现在/proc目录中的一些特定文件中,这样相当于将不可见的内核中的数据结构以可视化的方式呈现给内核的开发者。
(6)proc文件系统给了开发者一种调试内核的方法:我们通过实时的观察/proc/xxx文件,来观看内核中特定数据结构的值。在我们添加一个新功能的前后来对比,就可以知道这个新功能产生的影响对还是不对。
(7)proc目录下的文件大小都是0,因为这些文件本身并不存在于硬盘中,他也不是一个真实文件,他只是一个接口,当我们去读取这个文件时,其实内核并不是去硬盘上找这个文件,而是映射为内核内部一个数据结构被读取并且格式化成字符串返回给我们。所以尽管我们看到的还是一个文件内容字符串,和普通文件一样的;但是实际上我们知道这个内容是实时的从内核中数据结构来的,而不是硬盘中来的。
sys文件系统
(1)sys文件系统本质上和proc文件系统是一样的,都是虚拟文件系统,都在根目录下有个目录(一个是/proc目录,另一个是/sys目录),因此都不是硬盘中的文件,都是内核中的数据结构的可视化接口。
(2)不同的是/proc中的文件只能读,但是/sys中的文件可以读写。读/sys中的文件就是获取内核中数据结构的值,而写入/sys中的文件就是设置内核中的数据结构的元素的值。
(3)历史上刚开始先有/proc文件系统,人们希望通过这种技术来调试内核。实际做出来后确实很有用,所以很多内核开发者都去内核调价代码向/proc目录中写文件,而且刚开始的时候内核管理者对proc目录的使用也没有什么经验也没什么统一规划,后来的结果就是proc里面的东西又多又杂乱。
(4)后来觉得proc中的内容太多太乱缺乏统一规划,于是乎又添加了sys目录。sys文件系统一开始就做了很好的规划和约定,所以后来使用sys目录时有了规矩。
四、随机数序列与伪随机数序列
linux中随机数相关API
(1)rand: 连续多次调用rand函数可以返回一个伪随机数序列
intrand(void);
intrand_r(unsigned int *seedp);
(1)单纯使用rand重复调用n次,就会得到一个0-RAND_MAX之间的伪随机数,如果需要调整范围,可以得到随机数序列后再进行计算。
(2)单纯使用rand来得到伪随机数序列有缺陷,每次执行程序得到的伪随机序列是同一个序列,没法得到其他序列
(3)原因是因为rand内部的算法其实是通过一个种子(seed,其实就是一个原始参数,int类型),rand内部默认是使用1作为seed的,种子一定的算法也是一定的,那么每次得到的伪随机序列肯定是同一个。
(4)所以要想每次执行这个程序获取的伪随机序列不同,则每次都要给不同的种子。用srand函数来设置种子。
(2). srand: 函数用来设置rand获取的伪随机序列的种子
voidsrand(unsigned int seed);
(1)在每次执行程序时,先用srand设置一个不同的种子,然后再多次调用rand获取一个伪随机序列,这样就可以每次都得到一个不同的伪随机序列。
(2)一般常规做法是用time函数的返回值来做srand的参数。
在linux系统中获取真正的随机数
(1)linux系统收集系统中的一些随机发生的事件的时间(譬如有人动鼠标,譬如触摸屏的操作和坐标等)作为随机种子去生成随机数序列。