我最近在 Linux 内核源代码中遇到了这个问题,我也很困惑。找到答案并不是最简单的,我提供了这个问题的答案,希望将来有人能看到答案,不会错过 cmets 中的答案。
正如@MarcGlisse 正确指出的那样,您在 GCC 文档中找不到 noderef 或 _address_space_ 因为它们不是 GCC 属性。它们仅对Sparse 有意义。这就是为什么像 __iomem 这样定义的原因
#ifdef __CHECKER__
#define __iomem __attribute__((noderef, address_space(2)))
#else
#define __iomem
#endif
在“正常”编译下,宏被定义但实际上被忽略了。如果启用了检查器,即 Sparse,则会对其进行仔细检查。
@alk 前段时间通过提供指向此LKML article 的链接发表评论,Linus 在其中很好地解释了事情。我在 2006 年第一次看到链接在 Linux Questions thread 中的这篇文章。奇怪的是,我的浏览器出于“安全原因”拒绝打开链接,我不得不在 LKML 档案中找到它。
我希望这有助于了解正在发生的事情。自从您在大约 2.5 年前提出这个问题以来,您可能已经发现情况确实如此。
编辑
答案被否决了。想可能是因为我忽略了为noderef 提供一个含义,所以我现在要提供一个。正如我在答案中提到的,它是 sparse 检查某些东西的信号:指针的 dereference。考虑这个简单的程序:
#include <stdio.h>
#ifdef __CHECKER__
#define __void_region __attribute__((noderef, address_space(2)))
#else
#define __void_region
#endif
int main(void)
{
int i;
void * __void_region pMemory = NULL;
pMemory = &i;
printf("i is: %d\n", *(int*)pMemory);
return 0;
}
当使用 sparse 进行检查时,我得到以下信息:
$ sparse foo.c
foo.c:14:9: warning: dereference of noderef expression
foo.c:16:37: warning: dereference of noderef expression
基本上,该定义通知 sparse 以发出取消引用 pMemory 的信号。这是一个无意义的程序,但在内核中,__iomem 永远不应被取消引用,而只能通过适当的 I/O 内核 API 访问。