Memory 直接在内存中写入数据与使用asm指令的区别
我正在阅读Linux内核。我对在内存中写入数据的方式很好奇 在驱动程序的某些部分中,他们使用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)
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)=结果相反,code>让编译器自由选择它喜欢的移动
指令,并且很可能会选择导致缓存线被拉入缓存的指令。如果您正在与内存映射设备交互,这可能不是您想要的。此指令用于最小化缓存污染,并且不能用c中的简单“=”运算符来完成。MOVTI:“使用非时态提示将源操作数(第二个操作数)中的双字整数移动到目标操作数(第一个操作数),以最大限度地减少写入内存期间的缓存污染。源操作数是一个通用寄存器。目标操作数是一个32位内存位置。”@john感谢您的回复。所以您的意思是“movnti”指令与“mov”几乎相同,并且关心缓存污染。对吗?@Devolus噢,谢谢!我以前没找到过。是的,我读过。但是它用在什么地方我不知道。。。我的内核不是非常先进的atm,我不知道如何在内核中使用它们。你提到了我想知道的。谢谢@托拉克,啊,我终于明白这到底在做什么了。我在考虑这个问题,只是从链接上看,不清楚这段代码的意图是什么,但是内存映射IO的提示现在清楚了+1\uu iomem
不是一个变量,它是一个稀疏的
注释。首先,write()
函数写入文件,而不是内存。只是说,“…@FrankKotler:这是Linux内核的\uu writel()
,而不是用户空间write()
好的。我的错误。我也在“读得太快”呢!对不起。