Linux驅動中的outb 與volatile

2021-06-18 03:06:02 字數 1010 閱讀 7339

在linux的驅動程式中,都會使用大量的outb、outw、inb、inw等等巨集來訪問硬體或暫存器。這些巨集的定義都在相應處理器體系下的include\asm目錄下的io.h中定義。追究下去,這些巨集最終就是乙個volatile變數的的賦值:

#define __arch_putb(v,a)      (*(volatile unsigned char *)(a) = (v))

#define __raw_writeb(v,a)    __arch_putb(v,a)

#define outb(v,p)                 __raw_writeb(v,__io(p))

在(*(volatile unsigned char *)(a) = (v))中,a是乙個實體地址(實位址,多數是特殊功能暫存器位址)。(volatile unsigned char *)對a進行型別轉換,成為乙個指向該位址指標,最後*(volatile unsigned char *)(a)引用該指針對該位址賦值v。這樣就可以達到訪問底層硬體的目的了。

應用程式中定義的變數都是經過優化的,即在執行的時候變數會暫存在cpu的cache中。cpu修改該變數都是修改cache中的值,而不會更新記憶體中的值。直到任務的切換或cache失效,cache中的值才會更新到記憶體中。這樣訪問硬體是沒有時效性的,即有可能程式對硬體操作了多次後,實際才對硬體操作一次。www.linuxidc.com而驅動程式必須要求每次操作都要對硬體起作用。所以,如果要訪問硬體就必須避免編譯器對其操作進行優化,使得cpu對硬體的操作不經過cache而直接訪問目標。用volatile宣告乙個變數就可以達到這個目的。     

volatile關鍵字是一種型別修飾符,用它宣告的變數表示可能被未知的因素(如:硬體等)更改。遇到這個關鍵字宣告的變數,編譯器對訪問該變數的**就不再進行優化,從而可以提供對特殊位址的穩定訪問。     

(*(volatile unsigned char *)(a) = (v))訪問的並不一定是實際的實體地址,可能是經過記憶體管理重新對映後的位址,也就是虛擬位址。只不過volatile是使變數訪問不經過cache優化。

Linux 驅動框架 驅動中的非同步

非同步io是對阻塞和輪詢io的機制補充,所謂非同步io就是在裝置資料就緒時主動通知所屬程序進行處理的機制。之所以說是非同步是相對與被通知程序的,因為程序不知道也無法知道什麼時候會被通知 這一機制非常類似於硬體上的中斷。非同步io的實現也依賴於linux核心程序的訊號機制,因為非同步io就是通過sig...

Linux驅動中的platform

從linux2.6核心起,引入一套新的驅動管理和註冊機制 platform device 和 platform driver linux 中大部分的裝置驅動,都可以使用這套機制,裝置用 platform device 表示 驅動用 platform driver 進行註冊。linux platfor...

linux驅動中的request irq

我是乙個linux菜鳥,學習初期,寫此小博不為推廣知識,只為總結心得,不準確之處還請看官擔當。驅動中的中斷機制大致如下 1 首先要為裝置向核心申請乙個中斷號,裝置向cpu發生中斷請求的本質,其實就是通過裝置的中斷控制器 interrupt controller 向cpu傳送中斷號,然後cpu根據中斷...