linux源码分析:__user __kernel宏

__user宏出现的地方有三处,__kernel宏有两处,但都挨着

静态检查

/ include / linux / compiler_types.h

#ifdef __CHECKER__
/* address spaces */
# define __kernel	__attribute__((address_space(0)))
# define __user		__attribute__((noderef, address_space(__user)))

这个__CHECKER__宏专门给sparse用的,sparse是一个静态检验代码的工具,这就是个标记用的。
demo

# define __user		__attribute__((noderef, address_space(__user)))
# define __kernel		__attribute__((noderef, address_space(0)))

int add(char __user *d){
    return 0;
}
int main(){
	char __user * d;
    add(d);
    return 0;
}

如果这样写,运行结果如下

pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ sparse main.c 
main.c:7:10: warning: non-ANSI function declaration of function 'main'
main.c:4:5: warning: symbol 'add' was not declared. Should it be static?
pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ make
gcc main.c
main.c:4:1: warning: ‘noderef’ attribute directive ignored [-Wattributes]
    4 | int add(char __user *d){
      | ^~~
main.c:4:1: warning: ‘address_space’ attribute directive ignored [-Wattributes]
main.c: In function ‘main’:
main.c:8:9: warning: ‘noderef’ attribute directive ignored [-Wattributes]
    8 |         char __user * d;
      |         ^~~~
main.c:8:9: warning: ‘address_space’ attribute directive ignored [-Wattributes]
./a.out

没啥事儿,也能编译过去。

demo

# define __user		__attribute__((noderef, address_space(__user)))
# define __kernel		__attribute__((noderef, address_space(0)))

int add(char *d){
    return 0;
}
int main(){
	char __user * d;
    add(d);
    return 0;
}

运行结果

pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ sparse main.c 
main.c:7:10: warning: non-ANSI function declaration of function 'main'
main.c:4:5: warning: symbol 'add' was not declared. Should it be static?
main.c:9:9: warning: incorrect type in argument 1 (different address spaces)
main.c:9:9:    expected char *d
main.c:9:9:    got char [noderef] __user *d
pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ make
gcc main.c
main.c: In function ‘main’:
main.c:8:9: warning: ‘noderef’ attribute directive ignored [-Wattributes]
    8 |         char __user * d;
      |         ^~~~
main.c:8:9: warning: ‘address_space’ attribute directive ignored [-Wattributes]
./a.out

看到了吧

main.c:9:9: warning: incorrect type in argument 1 (different address spaces)
main.c:9:9:    expected char *d
main.c:9:9:    got char [noderef] __user *d

他说这不是正确的类型,因为你实参加了形参没加,但也能编译过去。

demo2

# define __user		__attribute__((noderef, address_space(__user)))
# define __kernel		__attribute__((noderef, address_space(0)))

int add(char __kernel *d){
    return 0;
}
int main(){
	char __user * d;
    add(d);
    return 0;
}

运行结果

pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ sparse main.c 
main.c:7:10: warning: non-ANSI function declaration of function 'main'
main.c:4:5: warning: symbol 'add' was not declared. Should it be static?
main.c:9:9: warning: incorrect type in argument 1 (different address spaces)
main.c:9:9:    expected char [noderef] *d
main.c:9:9:    got char [noderef] __user *d
pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ make
gcc main.c
main.c:4:1: warning: ‘noderef’ attribute directive ignored [-Wattributes]
    4 | int add(char __kernel *d){
      | ^~~
main.c:4:1: warning: ‘address_space’ attribute directive ignored [-Wattributes]
main.c: In function ‘main’:
main.c:8:9: warning: ‘noderef’ attribute directive ignored [-Wattributes]
    8 |         char __user * d;
      |         ^~~~
main.c:8:9: warning: ‘address_space’ attribute directive ignored [-Wattributes]
./a.out
pipishuo@pipishuo-OMEN-by-HP-Laptop-16-b0xxx:~/Desktop/knowledge/technology/_user$ 

一样的。
说白了就是给开发者提示用的,你这指针指的用户空间,结果你传到内核空间,那肯定有问题。

编译

/ include / linux / compiler_types.h

# define __kernel
# ifdef STRUCTLEAK_PLUGIN
#  define __user	__attribute__((user))
# else
#  define __user	BTF_TYPE_TAG(user)
# endif

这一个kernel好解释了,就是啥也不起作用
STRUCTLEAK_PLUGIN 刚查了下,这个好像是gcc的一个插件,如果定义了的话,user宏就变成

#  define __user	__attribute__((user))

功能基本跟上面1提到的一样。那为啥kernel就给省略了,我猜呀,可能编译时也会去查吧,因为这些变量,除了标记为__user的,其余肯定在内核空间内,因为我们编的就是内核,所以把kernel省略了。

#if defined(CONFIG_DEBUG_INFO_BTF) && defined(CONFIG_PAHOLE_HAS_BTF_TAG) && \
	__has_attribute(btf_type_tag) && !defined(__BINDGEN__)
# define BTF_TYPE_TAG(value) __attribute__((btf_type_tag(#value)))
#else
# define BTF_TYPE_TAG(value) /* nothing */
#endif

#  define __user	BTF_TYPE_TAG(user)

这个跟什么BTF有关,我看了下,基本默认配置时,就把他配置为N,所以基本就是没啥用。

总结

看代码时基本可忽略

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值