Linux學習一 I/O內存分配與I/O訪問

一:有的歐洲國家語言用的字母比26個多,佔用了ASCII碼錶中&和其它符號的位置,所以規定了一些操作符的特殊表示方法。

C++中有些用的二聯符和三聯符


??=  表示 #    ??)   表示]      ??(   表示[
??!  表示 |     ??/   表示\      ??-   表示~
??>  表示 }     ??<   表示(     ??'   表示^

<%  表示 {      and    表示&&    and_eq 表示&=
%>  表示 }      bitor  表示|     or_eq  表示|=
<:  表示 [      or     表示||    xor_eq 表示^=
:>  表示 ]      xor    表示^     not    表示!
%:  表示 #      compl  表示~     not_eq 表示!=

%:%:表示 ##     bitand 表示&


二:Linux的輪詢操作;Linux在驅動層提供了一種非常聰明的方法,就是在驅動層的file_operation中實現poll方法。 poll方法由操作系統每隔一段時間調用一次,當poll 返回1時, 表示可以操作;

使用非阻塞的I/O 的應用程序通常會使用select () 和 poll ()實現輪詢操作。 用於查詢設備的狀態。


三:Linux設備驅動之內存分配與I/O 訪問

 幾乎每一種外設都通過讀寫設備上的寄存器來控制或數據操作; 外設寄存器也稱爲 I/O端口; 通常包括控制寄存器, 狀態寄存器, 數據寄存器 3大類;CPU對外設I/O進行編址有兩種方式: I/O映射方式,  內存映射方式;  arm9處理器只實現了一個屋裏地址空間,而CPU將外設的I/O 物理地址映射到CPU的單一物理地址空間,因此成爲內存的一部分,這是CPU就像訪問內存一樣訪問外設的I/O 端口,這就是所謂的內存映射方式;

Linux中,我們將基於I/O映射方式的或基於內存映射方式的I/O端口成爲  I/O 區域, 也就是我們所說的 I/O資源;

當編寫的程序在CPU中運行時就成爲一個系統進程,會涉及到5種不同的數據段;代碼段數據段,就是存放程序靜態分配非變量和全局變量;BSS段,BSS段包含程序中衛初始化的全局變量,BSS段在內存中全部置零;,存放進程運行中被動態分配的內存段;,是用戶存放程序臨時創建的局部變量;

四:操作I/O內存

1、申請I/O內存,必須先非配,在<linux/ioport.h>中定義, request_mem_region()函數分配一個開始於start 的len字節的i/o內存區;成功返回非null;

struct resource *request_men_region(unsigned long start, unsigned long len, char *name);

 2、映射,在訪問i/o內存之前,分配i/o內存並不是唯一要求的步驟,還必須保證內核可存取該i/o 內存; ioremap()函數將i/o內存區映射到虛擬地址;參數phys_addr爲要映射到i/o內存起始地址,size爲要映射的i/o大小;

void *ioremap(unsigned long phys_addr, unsigned long size);

3、方位i/o內存;ioremap返回的地址不可以直接解引用,應當使用內核提供的訪問函數,在<asm/io.h>文件中,I/O內存讀函數的參數addr 應該是從ioremap獲得的地址(可能包含一個偏移地址),返回值是從給定的I/O 內存讀取到的值;

unsigned int ioread8(void *addr);

unsigned int ioread16(void *addr);

unsigned int ioread32(void *addr);

I/O內存寫函數,參數addr同I/O內存讀函數,參數value爲要寫的值;

void iowrite8(u8 value, void *addr);

void iowrite16(u16 value, void *addr);

void iowrite32(u32 value, void *addr);

以下這些函數將一系列值讀取或寫到一個給定的I/O內存地址,從給定的buf讀或寫 count個值到給定的addr。

void ioread8_rep(void *addr, void *buf, unsigned long count);

void ioread16_rep(void *addr, void *buf, unsigned long count);

void ioread32_rep(void *addr, void *buf, unsigned long count);

void iowrite8_rep(void *addr, const void *buf, unsigned long count);

void iowrite16_rep(void *addr, const void *buf, unsigned long count);

void iowrite32_rep(void *addr, const void *buf, unsigned long count);

需要操作一塊I/O地址時,課使用夏磊函數

void memset_io(void *addr, u8 value, unsigned int count);

void memcpy_fromio(void *dest, void *source, unsigned int count);

void memcpy_toio(void *dest, void *source, unsigned int count);

4、釋放I/O內存步驟

void iounmap(void *addr);

void release_mem_region(unsigned long start, unsigned long len);


不管是I/O內存還是I/O端口,Linux2.6版本內核提供了一個ioport_map函數;重新映射count個 I/O端口,使他們看起來像I/O內存,驅動在ioport_map返回的地址上使用ioread8和同類函數;


























發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章