在编写设备驱动程序时,linux中的iomem有什么用途?

在编写设备驱动程序时,linux中的iomem有什么用途?,linux,memory-management,linux-kernel,linux-device-driver,Linux,Memory Management,Linux Kernel,Linux Device Driver,我已经看到\uu iomem用于存储ioremap()的返回类型,但是我在ARM体系结构中使用了u32,它工作得很好 那么,\u iomem在这里有什么区别呢?在什么情况下我应该准确地使用它?很多类型转换都会“很好地工作”。但是,这不是很严格。没有什么可以阻止您将u32强制转换为u32*并取消对它的引用,但这并不遵循内核API,而且容易出错 \uu iomem是一个cookie,用于查找内核中可能的编码错误。如果不在启用稀疏的情况下编译内核代码,iomem将被忽略 使用Sparse,首先安装它,

我已经看到
\uu iomem
用于存储
ioremap()
的返回类型,但是我在ARM体系结构中使用了
u32
,它工作得很好


那么,
\u iomem
在这里有什么区别呢?在什么情况下我应该准确地使用它?

很多类型转换都会“很好地工作”。但是,这不是很严格。没有什么可以阻止您将
u32
强制转换为
u32*
并取消对它的引用,但这并不遵循内核API,而且容易出错

\uu iomem
是一个cookie,用于查找内核中可能的编码错误。如果不在启用稀疏的情况下编译内核代码,
iomem
将被忽略

使用Sparse,首先安装它,然后将
C=1
添加到
make
调用中。例如,在构建模块时,请使用:

make -C $KPATH M=$PWD C=1 modules

\uu iomem
的定义如下:

#定义uuiome uuuuu属性uuuu((noderef,地址空间(2)))
为所有I/O访问添加(并要求)类似cookie的
\uuu iomem
,这是一种更加严格并避免编程错误的方法。您不想从具有绝对地址的I/O内存区域读/写,因为您通常使用虚拟内存。因此,

void\u iomem*ioremap(物理地址偏移量,无符号长尺寸);
通常被调用以获取I/O物理地址的虚拟地址
偏移量
,以字节为单位指定长度
大小
ioremap()
返回一个带有
\uIomem
cookie的指针,因此现在可以将它与接受
\uIomem
地址的内联函数一起使用,例如
readl()
/
iowrite32()
(尽管现在最好使用更显式的宏
ioread32()

另外,Sparse使用
noderef
属性来确保不取消引用
iomem
指针。解引用应该适用于I/O确实是内存映射的某些体系结构,但其他体系结构使用特殊指令访问I/O,在这种情况下,解引用将不起作用

让我们看一个例子:

void*io=ioremap(42,4);
我不高兴:

warning: incorrect type in initializer (different address spaces)
    expected void *io
    got void [noderef] <asn:2>*
他也不高兴:

warning: dereference of noderef expression
在上一个示例中,第一行是正确的,因为
ioremap()
将其值返回给
\uu iomem
变量。但是,我们尊重它,我们不应该这样做

这让斯派斯很高兴:

void\uuu iomem*io=ioremap(42,4);
pr_信息(“%x\n”,ioread32(io));
底线:在需要的地方(作为返回类型或参数类型)始终使用
\uu iomem
,并使用Sparse确保这样做。另外:不要取消引用
iomem
指针


编辑:这里有一个关于
\uu iomem
的开始以及使用它的函数的精彩解释。

很好的解释。有一些很好的参考资料就说到点子上了。