第一点

关于时间的概念

GMT时间

格林尼治时间,可自行百度!

UTC时间

现在常用的时间概念!自行百度

计算机中的时间

点时间(RTC:实时时间)

段时间(定时器实现)

第二点

linux系统中的时间

jiffies的引入

他是内核中的一个全局变量,用来记录以内核节拍时间(也就是调度时间、取决于操作系统的配置、一般为1ms/10ms)为时间单位的一个时间长度。

linux系统如何记录时间

liunx内核启动时,jiffies就有一个基准值(是通过调用RTC所获得的当前时间点值换算成的jiffies值)然后,内核每过一个时间节拍,jiffies就会加一。

如果想计算开机多长时间:(就用当前jiffies值减去基值)*节拍时间

linux中时间相关的函数调用

常用的API和C库函数有九个

time、ctime、localtime gettimeofday  settimeofday............

之间的的关系如下图,基本都是围绕着time去做!!

time系统调用返回当前时间 距离1970-01-01 00:00:00+0000(UTC)以秒为单位的秒数;(这个秒数就是time内部用jiffies换算得到的) 

gettimeofday返回的时间是由struct timevai和struct timezone这两个结构体来共同表示的,其中timeval表示时间,timezone表示时区!

settimeofday是用来设置当前时间和时区的!

不管使用哪一种系统调用,最终得到的时间本质上都是一个时间(这个时间最终都是从内核中记录的jiffies中计算得到的)只不过不同的函数返回的时间精度不同。

第三点

相关的时间API实战

time

由这个函数可以看出来,他的参数为输出型参数,也就是他的返回值是可以通过两个途径来得到,一个是time_t 另一个就是形式参数的指针。

上面函数中,我们不想以指针参数的形式返回,所以在参数的地方传了NULL(图一)

如果想以参数的形式达到目的,参考图二

   这个时间是现在时间与标准起点时间秒间隔

 最后的运行结果如上!

ctime

分析可得,这个函数的形式参数是一个输入型参数,返回值是一个char *类型的字符指针类型。传入的参数就用上个函数的返回值!

第一种方式就是定义一个char *p,ctime函数返回的是一个静态结构体的首地址,然后把这个地址存在p里面,然后打印p(以打印字符串格式)

第二种方式就是直接打印ctime(&tNow) 

 

结果如上!可以看到他的格式是固定的

上面的程序使用的就是第一种方法!

gmtime

 

 由上面定义可知,gmtime的返回值为一个结构体指针,输入参数是由time函数得到的返回值,

gmtime_r返回值为一个结构体指针(地址 ),输入参数是由time函数得到的返回值和一个结果结构体指针。那我们就以gmtime_r为例测试!

图二代表的是结果结构体指针里面所存储的元素!

   首先定义一个结构体tmNow

 然后将这个结构体清空!

gmtime获取的时间中,年份是以1970为基准的差值,月份是0表示1月,小时数是以UTC时间的0时区为标准的小时数(北京市东8区,因此北京时间比这个大8)

localtime和gmtime的唯一区别就是localtime以当前计算机中设置的时区为小时的时间基准,其余一样!

mktime

从OS中读取时间的时候是用不到这个函数的, 他是用来向操作系统设置时间的!

asctime

asctime得到的是一个固定格式的字符串格式的当前时间,效果是和ctime一样的,区别是ctime从time_t出发,而asctime从struct tm出发!

strftime

如果想自定义得到的时间字符串的格式,就用strftime这个函数!

这个函数有四个参数,他会把const struct tm *tm得到的时间对照const char *format的格式改掉。字符串会放到char *s这个buf中去,buf的大小是size_t max

针对于char *s的说明,为什么说他是个buf???

对于char * s来说,s指向的是内存某个地方的开头的首地址,所以相当于开辟了一段内存去存储数据,就可以 当buf来用。

gettimeofday和settimeofday 

//定义返回值 

前面讲到的函数都是以秒为最小时间的,这两个函数可以精确到微秒!!!(-480/60=-8,也就是东八区)

第四点 

linux随机数

随机数与伪随机数

没有真正意义上的随机数,我们现在所说的随机数都是伪随机数。随机数的应用场景比如商场的抽奖。

linux随机数相关的API-rand

 如果我想得到6以内的随机数,怎样处理呢???-对6取余

 

但是rand函数有个缺点,就是如果使用这个程序。他每次得到的伪随机数都是一样的!

原因是rand内部的算法是一样的,他每次是由某一个值作为起始值,然后在这个算法的基础上得到这个随机数,而这个起始值每次都一样,就是1,所以要想每次结果不同,就得换这个起始值,因此引进了srand这个函数!

总结

在每次执行程序时,先用srand设置得到一个不同的种子,然后再多次调用rand获取一个伪随机序列,这样就可以每次得到不同的伪随机序列!

第五点

proc文件系统介绍

调试程序进阶

单步调试->Printf打印信息调试->日志信息调试   

引出问题,以上的调试都是基于内核的,那么内核调试谁来关心呢?

proc虚拟文件系统工作原理

linux内核是一个非常庞大、非常复杂的一个单独的程序,对于这样一个程序调试是非常复杂的。

要是给内核这么一个庞大的项目增加一个或者减少一个功能是非常麻烦的。

为了降低内核调试和学习的难度,内核开发者给内核中增添了一些属性部门用于调试内核,proc文件系统就是一个尝试。

proc文件系统思路:在内核中建立一个虚拟文件系统/Proc,在内核运行时将内核中一些关键的数据结构以可视化的方式呈现个开发者。

这样呢,就相当于提供给了开发者一种调试思路:我们通过实时观察/proc/xxx文件,来观看内核中特定数据结构的值,在我们增添或者减少一个新功能前后对比,就能知道这个新功能产生的影响对不对。

常见的proc文件的介绍

/proc目录下,以数字命名的的目录表示当前一个运行的进程,目录名即为进程PID,其内的目录和文件给出了一些关于该进程的信息!

sys文件系统

sys文件系统本质上与proc文件系统一样,都是虚拟文件系统,都是在根目录下有个目录,因此都不是硬盘中的文件,都是内核中数据结构的可视化接口!

不同的是/proc中的文件只能读,但是/sys中的文件可以读写,(读是获取内核文件中数据结构的值,写是写入/sys中的文件就是设置内核中的数据结构的元素的值)

功能相似,为啥要有/proc和/sys?

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐