jiffies变量是定义在链接脚本arch/i386/kernel/vmlinux.lds.S里面的:
- OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
- OUTPUT_ARCH(i386)
- ENTRY(phys_startup_32)
- jiffies = jiffies_64;
是说定义不知道是否妥当,因为这个链接脚本里面的定义概念已经不是我们时常接触的C语言的变量定义的概念了。我们都知道C语言对于变量的定义会为其分配存储空间。然而:
在链接脚本中,这个定义却只是指定了:jiffies符号地址与jiffies_64这个符号的符号地址相同
换句话说:jiffies变量与jiffies_64变量位于同一地址。
我们看一下System-map里这两个符号的地址。
- c06fac00 D jiffies
- c06fac00 D jiffies_64
的确是一样的。而jiffies_64的定义在kernel/time.c中。如下:
- u64 jiffies_64 __cacheline_aligned_in_smp = INITIAL_JIFFIES;
或许你会有些疑问:为什么要把jiffies变量定义在链接脚本里面?
我想是因为:首先C语言中没有很好的别名机制(两个变量共享同一地址,两个变量只不过是不同名称的相同内存地址的内存标签),其次内核代码很少有用到jiffies变量的地方,因为jiffies会产生溢出。而jiffies变量被更多的使用在驱动程序中。
为了解决jiffies(u32)变量的溢出问题,内核利用了下面几个宏对其处理。
- 117 #define time_after(a,b) \
- 118 (typecheck(unsigned long, a) && \
- 119 typecheck(unsigned long, b) && \
- 120 ((long)(b) - (long)(a) < 0))
- 121 #define time_before(a,b) time_after(b,a)
- 122
- 123 #define time_after_eq(a,b) \
- 124 (typecheck(unsigned long, a) && \
- 125 typecheck(unsigned long, b) && \
- 126 ((long)(a) - (long)(b) >= 0))
- 127 #define time_before_eq(a,b) time_after_eq(b,a)
对于这几个宏是如何解决溢出 可以google一下,网上这类文章很多。
对于time_after等比较jiffies先/后的宏,两个值的取值应当满足以下限定条件:
- 首先a超越b的时间不能大于有符号数所能表示的最大值
- 对于32位无符号整型,两个值之间相差从逻辑值来讲应小于2147483647。对于HZ=100,那么两个时间值之间相差不应当超过2147483647/100秒 = 0.69年 = 248.5天。对于HZ=60,那么两个时间值之间相差不应当超过2147483647/60秒 = 1.135年。在实际代码应用中,需要比较先/后的两个时间值之间一般都相差很小,范围大致在1秒~1天左右,所以以上time_after等比较时间先/后的宏完全可以放心地用于实际的代码中。
阅读(2019) | 评论(0) | 转发(0) |