Memory 直接在内存中写入数据与使用asm指令的区别

Memory 直接在内存中写入数据与使用asm指令的区别,memory,assembly,Memory,Assembly,我正在阅读Linux内核。我对在内存中写入数据的方式很好奇 在驱动程序的某些部分中,他们使用asm/io.h中定义的writel()函数,在该函数的定义中,他们使用movinti指令-实际上我不理解该指令的含义,除了它是一种mov指令 无论如何,当在内存中写入数据时,使用writel()和直接在内存中写入有什么区别,例如**address=data 情况如下: static inline void __writel(__u32 val, volatile void __iomem *addr)

我正在阅读Linux内核。我对在内存中写入数据的方式很好奇

在驱动程序的某些部分中,他们使用
asm/io.h
中定义的
writel()
函数,在该函数的定义中,他们使用
movinti
指令-实际上我不理解该指令的含义,除了它是一种
mov
指令

无论如何,当在内存中写入数据时,使用
writel()
和直接在内存中写入有什么区别,例如
**address=data

情况如下:

static inline void __writel(__u32 val, volatile void __iomem *addr)
{
    volatile __u32 __iomem *target = addr;
    asm volatile("movnti %1,%0"
             : "=m" (*target)
             : "r" (val) : "memory");
}
这是另一种情况:

*(unsigned int*)(MappedAddr+pageOffset) = result;

writel
看起来像是针对内存映射IO的,有一些东西可以支持这一点,首先是使用
volatile
指针(它可以防止优化,例如重新排序调用或优化调用等)和非临时指令(IO写入/读取不应缓存)当然,
iomem
注释似乎也支持这一点。

如果我理解正确,那么使用
moventi
指令将最小化对处理器数据缓存的影响。使用
*(unsigned int*)(MappedAddr+pageOffset)=结果让编译器自由选择它喜欢的
移动
指令,并且很可能会选择导致缓存线被拉入缓存的指令。如果您正在与内存映射设备交互,这可能不是您想要的。

此指令用于最小化缓存污染,并且不能用c中的简单“=”运算符来完成。MOVTI:“使用非时态提示将源操作数(第二个操作数)中的双字整数移动到目标操作数(第一个操作数),以最大限度地减少写入内存期间的缓存污染。源操作数是一个通用寄存器。目标操作数是一个32位内存位置。”@john感谢您的回复。所以您的意思是“movnti”指令与“mov”几乎相同,并且关心缓存污染。对吗?@Devolus噢,谢谢!我以前没找到过。是的,我读过。但是它用在什么地方我不知道。。。我的内核不是非常先进的atm,我不知道如何在内核中使用它们。你提到了我想知道的。谢谢@托拉克,啊,我终于明白这到底在做什么了。我在考虑这个问题,只是从链接上看,不清楚这段代码的意图是什么,但是内存映射IO的提示现在清楚了+1
\uu iomem
不是一个变量,它是一个
稀疏的
注释。首先,
write()
函数写入文件,而不是内存。只是说,“…@FrankKotler:这是Linux内核的
\uu writel()
,而不是用户空间
write()
好的。我的错误。我也在“读得太快”呢!对不起。