linux 3.0.35 内核下 include/linux/compiler.h 关于__iomem
Sparse工具检测使用的属性定义
__CHECKER__ 宏在通过Sparse(Semantic Parser for C)工具对内核代码进行检查时会使用。在使用make C=1或C=2
时便会调用该工具,这个工具可以检查在代码中声明了sparse所能检查到的相关属性的内核函数和变量。如下示:
#ifdef __CHECKER__
sparse所能检查的相关属性,定义如下:
# define __user __attribute__((noderef, address_space(1))) # define __kernel __attribute__((address_space(0))) # define __safe __attribute__((safe)) # define __force __attribute__((force)) # define __nocast __attribute__((nocast)) # define __iomem __attribute__((noderef, address_space(2))) # define __acquires(x) __attribute__((context(x,0,1))) # define __releases(x) __attribute__((context(x,1,0))) # define __acquire(x) __context__(x,1) # define __release(x) __context__(x,-1) # define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0) # define __percpu __attribute__((noderef, address_space(3)))
关于地址空间:
sparse 把地址空间分为3部分,0表示普通地址空间,对内核来说就是地址空间。1表示用户地址空间。2表示设备地址映射空间,
即设备寄存器的地址空间。
address_space(0) 普通地址空间
address_space(1) 代表用户地址空间
address_space(2) 代表设备寄存器的地址空间
关于以上代码的解释:
__user
特性用来修饰一个变量的地址,该变量必须是非解除参考(no dereference) 即地址是有效的,并且变量所在的地址空间必须为1
__kernel
特性修饰变量为内核地址,为内核代码里面默认的地址空间。
__safe
特性声明该变量为安全变量,这是为了避免在内核函数未对传入的参数进行校验就使用的情况下,会导致编译器对其报错或输
出告警信息。通过该特性说明该变量不可能为空。
__force
特性声明该变量是可以强制类型转换的。
__nocast
声明该变量参数类型与实际参数类型要一致才可以。
__iomem
声明地址空间是设备地址映射空间。
__acquires
为函数属性定义的修饰,表示函数内,该参数的引用计数值从1变为0。
__releases
与__acquires相反,这一对修饰符用于Sparse在静态代码检测时,检查调用的次数和匹配请求,经常用于检测lock的获取和释放。
__acquire
表示增加变量x的计数,增加量为1。
__release
表示减少变量x的计数,减少量为1。这一对与上面的那一对是一样,只是这一对用在函数的执行过程中,都用于检查代码中
出现不平衡的状况。
__cond_lock
用于表示条件锁,当c这个值不为0时,计数值加1,并返回1。