一、I/O寄存器和常规内存
-
尽管硬件寄存器和内存才能非常相似,但程序员在访问I/O寄存器的时候必须注意避免由于CPU或编译器不恰当的优化而改变预期的I/O动作。I/O寄存器与RAM的最主要的区别就是IO操作具有边际效应,而内存没有:内存写操作的唯一结果就是在指定位置存储一个数值;内存读操作则仅仅返回指定位置最后一次写入的数值。由于内存访问速度对CPU的性能至关重要,而且也没有边际效应,所以可用多种方法进行优化,如使用高速缓存保存数值、重新排序读\写指定。
-
编译器能够将数值缓存在CPU寄存器中而不写入内存,即使存储数据,读写操作也多能在高速缓存中进行而不用访问物理RAM。无论在编译器一级或是硬件一级,指令的重新排序都有可能发生:一个指令序列如果以不同于程序文本中的次序运行常常能执行得更快,例如防止RISC处理器流水线的互锁时就是如此。对常规内存进行这些优化的时候,优化过程是透明的,而且效果良好。但对IO操作来说这些优化很可能就是致命的错误,这便是边际效应的干扰。编译器或CPU可能会自作聪明地重新排序所要求的操作,结果会发生奇怪的错误,并且很难调试。因此,驱动程序必须确保不使用高速缓存,并且在访问寄存器时不发生读写指令的重新排序。
-
由于硬件自身缓存引起的问题很好解决:只要把底层硬件配置程在访问IO区域时禁止硬件缓存,由编译器优化和硬件重新排序所引起的问题的解决办法是:对硬件必须以特定的顺序执行的操作之间设置内存屏障。
void rmb(void); void read_barier_depends(void) void wmb(void); void mb(void);
这些函数在已编译的指令流中插入硬件内存屏障,rmb保证了屏障之前的读操作一定会在后来的读操作执行之前完成。wmb保证写操作不会乱序,mb指令保证了两者都不会。
- 内存屏障会影响系统性能,所以应该只用于真正需要的地方。不同类型的内存屏障对性能的影响也不尽相同。比如x86上,处理器之外的写入操作不会被重新排序,因此,wm

博客探讨了I/O寄存器与常规内存的区别,强调了IO操作的边际效应以及编译器和硬件优化可能带来的问题。介绍了内存屏障在确保I/O操作顺序中的作用,以及如何安全地访问和管理IO内存,包括分配、映射和使用包装函数的重要性。
最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



