有時, 乙個共享資源是乙個簡單的整數值. 假設你的驅動維護乙個共享變數 n_op, 它告知有多少裝置操作目前未完成. 正常地, 即便乙個簡單的操作例如:
n_op++;
可能需要加鎖. 某些處理器可能以原子的方式進行那種遞減, 但是你不能依賴它. 但是乙個完整的加鎖體制對於乙個簡單的整數值看來過分了. 對於這樣的情況, 核心提供了乙個原子整數型別稱為 atomic_t, 定義在 .
乙個 atomic_t 持有乙個 int 值在所有支援的體系上. 但是, 因為這個型別在某些處理器上的工作方式, 整個整數範圍可能不是都可用的; 因此, 你不應當指望乙個 atomic_t 持有多於 24 位. 下面的操作為這個型別定義並且保證對於乙個 smp 計算機的所有處理器來說是原子的. 操作是非常快的, 因為它們在任何可能時編譯成一條單個機器指令.
void atomic_set(atomic_t *v, int i);
atomic_t v = atomic_init(0);
設定原子變數 v 為整數值 i. 你也可在編譯時使用巨集定義 atomic_init 初始化原子值.
int atomic_read(atomic_t *v);
返回 v 的當前值.
void atomic_add(int i, atomic_t *v);
由 v 指向的原子變數加 i. 返回值是 void, 因為有乙個額外的開銷來返回新值, 並且大部分時間不需要知道它.
void atomic_sub(int i, atomic_t *v);
從 *v 減去 i.
void atomic_inc(atomic_t *v);
void atomic_dec(atomic_t *v);
遞增或遞減乙個原子變數.
int atomic_inc_and_test(atomic_t *v);
int atomic_dec_and_test(atomic_t *v);
int atomic_sub_and_test(int i, atomic_t *v);
進行乙個特定的操作並且測試結果; 如果, 在操作後, 原子值是 0, 那麼返回值是真; 否則, 它是假. 注意沒有 atomic_add_and_test.
int atomic_add_negative(int i, atomic_t *v);
加整數變數 i 到 v. 如果結果是負值返回值是真, 否則為假.
int atomic_add_return(int i, atomic_t *v);
int atomic_sub_return(int i, atomic_t *v);
int atomic_inc_return(atomic_t *v);
int atomic_dec_return(atomic_t *v);
就像 atomic_add 和其類似函式, 除了它們返回原子變數的新值給呼叫者.
如同它們說過的, atomic_t 資料項必須通過這些函式訪問. 如果你傳遞乙個原子項給乙個期望乙個整數引數的函式, 你會得到乙個編譯錯誤.
你還應當記住, atomic_t 值只在當被置疑的量真正是原子的時候才起作用. 需要多個 atomic_t 變數的操作仍然需要某種其他種類的加鎖. 考慮一下下面的**:
atomic_sub(amount, &first_atomic);
atomic_add(amount, &second_atomic);
從第乙個原子值中減去 amount, 但是還沒有加到第二個時, 存在一段時間. 如果事情的這個狀態可能產生麻煩給可能在這 2 個操作之間執行的**, 某種加鎖必須採用.
Linux核心之字元裝置驅動
學習計畫 1.vfs 虛擬檔案系統 vfs的作用就是採用標準的unix系統呼叫讀寫位於不同物理介質上的不同檔案系統。vfs是乙個可 以讓open read write 等系統呼叫不用關心底層的儲存介質和檔案系統型別就可以工作的 粘合層。在古老的dos作業系統中,要訪問本地檔案系統之外的檔案系統需要使...
linux 核心 驅動
首先 1.建立裝置 分配cdev結構體 if globalmem major 手動分配 ret register chrdev region devno,1,globalmem else globalmem 提供給上層使用 2 建立核心裝置 struct globalmem dev globalme...
Linux核心併發機制 原子操作
很多人會問這樣的問題,linux核心中提供了各式各樣的鎖機制到底有何作用?追根到底其實是由於作業系統中存在多程序對共享資源的併發訪問,從而引起了程序間的競態。這其中包括了我們所熟知的smp系統,多核間的相互競爭資源,單cpu之間的相互競爭,中斷和程序間的相互搶占等諸多問題。所謂的原子操作,就是該操作...