一、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);
这些函数在已编译的指令流中插入硬件内存屏障ÿ