CPU通過硬件設備的寄存器讀寫設備IO。
對X86平臺,這些寄存器位于專門的IO空間中,稱為IO端口;而對于其他大多是CPU,IO寄存器是映射到普通內存中,沒有劃出特別的空間,因此稱作IO內存。
對IO端口的操作流程
op1=>operation: request_region
op2=>operation: inb(),outb()等
op3=>operation: release_region
op1->op2->op3
對IO內存操作
op1=>operation: request_mem_region
op2=>operation: ioremap()
op3=>operation: inb(),outb()等
op4=>operation:
op5=>operation: release_mem_region
op1->op2->op3->op4->op5
可見IO內存操作比IO端口多一個io映射的動作:
void *ioremap(unsigend long *add, unsigned long size)
對IO端口的操作函數主要是inb/w/l,outb/w/l等。
以及連續讀寫 insb/w/l、outsb/w/l等。
對于非x86的CPU,一般都是用IO內存方法,讀寫接口如下:
unsigned int readb/w/l(addr)
writeb/w/l(value, addr)
//LDD中建議使用下面接口,因為會進行類型檢查,更加安全
unsigned int ioread8/16/32(addr)
void iowrite8/16/32(value, addr)
void ioread8/16/32/_rep(addr, buf, count) //連續讀寫
void iowrite8/16/32/_rep(addr, buf, count)
//整塊操作, 與對應C庫函數意義相似
void memset_io(addr, value, count)
void memcpy_fromio(dest, source, count)
void memcpy_toio(dest, source, count)
關于IO屏障的問題,
為了防止硬件優化帶來的讀寫亂序而是用內存屏障
相關函數有 rmb() wmb() mb()等。
參考內核源碼,readb,writeb等函數已經使用了屏障,因此不需要再寫一次:
linux-3.18.27\arch\arm\include\asm\io.h
/* IO barriers */
#ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
#include <asm/barrier.h>
#define __iormb() rmb()
#define __iowmb() wmb()
#else
#define __iormb() do { } while (0)
#define __iowmb() do { } while (0)
#endif
//-----------------------------------------------------------------------------
#define readb(c) ({ u8 __v = readb_relaxed(c); __iormb(); __v; })
#define writeb(v,c) ({ __iowmb(); writeb_relaxed(v,c); })
上面 CONFIG_ARM_DMA_MEM_BUFFERABLE 這個宏,是在內核編譯時配置的,有相關說明:
Historically, the kernel has used strongly ordered mappings to
provide DMA coherent memory. With the advent of ARMv7, mapping
memory with differing types results in unpredictable behaviour,
so on these CPUs, this option is forced on.
大概是說對arm中采用strongly ordered mappings的cpu不需要內存壁障,否則就要增加 內存壁障來保證安全。