"address_space()" 在 linux 内核中定义为 "Sparse" 注释

"address_space()" definition as a "Sparse" annotation in the linux kernel

我遇到了一些定义如下的宏:

#ifdef __CHECKER__
# define __user     __attribute__((noderef, address_space(1)))

而且我知道这些仅用于稀疏(__CHECKER__) 并且 GCC 忽略它们 completely.But 我不明白的是address_space() 到底是什么意思?它的可能值是什么?看起来它的唯一文档是大约 16 年前的 post from linus in the mailing list,上面写着:

When you do use parse, it is another matter entirely. For "sparse", that "__iomem" has lots of meaning:
# define __iomem __attribute__((noderef, address_space(2)))

ie "iomem" means two separate things: it means that sparse should complain if the pointer is ever dereferenced (it's a "noderef" pointer) directly, and it's in "address space 2" as opposed to the normal address space (0).

this and this 等类似的问答中,我发现 3 表示 per-cpu 指针和 1 似乎与从 userspace.And 收到的指针有关,也与 0 的普通指针有关。

但是 address_space(2) 到底是什么意思?
{0,1,2,3} 是唯一可能的值吗?

谢谢。

address_space()noderef 是属性。可能令人困惑的是它们不是 GCC 属性。它们是 Sparse 属性,因此只有在定义 __CHECKER__ 并启用 Sparse 时,它们才对 Sparse 有意义。

address_space() 属性对标记它的指针施加了特定限制。我的理解是,作为参数的数字是任意选择的,表示指针属于某个 class。因此,如果你遵循规则,你应该清楚地注释一个指针属于特定的 class(例如 __user__iomem 等),而不是混合来自不同 [=36] 的指针=]是的。使用这些注释,Sparse 作为静态检查器可以帮助您发现不正确使用的情况。

对于 address_space(2) 又名 __iomem 我在这里找到了一个很好的描述:What is the use of __iomem in linux while writing device drivers? Linus 的 post 也是一个很好的描述。

除了 {0,1,2,3} 还有 {4}__rcu 指针标记为分开 class。我认为目前没有更多。

此属性将用于指针,以指定相应内存的地址 space 不同于通常的内核内存。因此,不能通过简单地取消引用指针来访问它,而是需要通过一些特定的函数集(或宏)来访问它。 Sparse 将具有不同地址 spaces 的指针视为不同的类型,并将警告混合地址 spaces.

的强制转换(隐式或显式)

地址space曾经用一个小数字来标识,但在当前的内核中使用了一个标识符。允许的值(对于内核)是:

  • __user/1:用于user-space内存(通过get_user()/put_user(), copy_from_user()访问/copy_to_user(), ...)
  • __iomem/2: 用于 I/O 内存(通过 ioread{8,16,32,64}(), writel()/readl(), .. .)
  • __percpu/3:用于'per-CPU'内存(要访问get_cpu_var()/put_cpu_var(),...,还需要专门分配或声明:alloc_percpu(), DECLARE_PER_CPU(), ...)
  • __rcu/4:用于 'RCU' 内存(通过 rcu_dereference(), ... 访问)
  • 0: 是默认值,用于普通内核内存。

某些文档可在 https://sparse.docs.kernel.org/en/latest/annotations.html 获得。