LDD 併發和競態

2021-10-04 18:40:14 字數 1596 閱讀 7867

1.正在執行的多個使用者空間程序可能以一種令人驚訝的組合方式訪問我們的**。

2.smp系統甚至可在不同的處理器上同時執行我們的**。

3.核心是可搶占的,驅動程式**可能在任何時候丟失對處理器的獨佔

4.裝置中斷時非同步事件,可能導致**的併發執行

5.核心還提供了許多可延遲**執行的機制,比如workqueue、tasklet、timer等,這些機制使**可在任何時候執行

6.在現代熱插拔世界,裝置可能在我們正在使用消失。

臨界區:在任意給定的時刻,**只能被乙個執行緒執行。

進入休眠:當乙個linux程序到達某個時間點,此時它不能進行任何處理時,它將進入休眠(或阻塞)狀態,這將把處理器讓給其他執行執行緒直到將來它能夠繼續完成自己的處理為止。

訊號量:可休眠的鎖機制。乙個訊號量本質上是乙個整數值,它和一對函式聯合使用,通常稱為p(希望進入臨界區的程序將在相關訊號量上呼叫p,如果訊號量大於0,則該值減一,程序進入。相反,訊號量的值為0或負數,程序必須等待其他人釋放)和v(程序釋放訊號量時呼叫,該函式增加訊號量的值,並在必要時喚醒等待的程序)

訊號量的實現:

struct semaphore;

宣告和初始化:sema_init(struct semaphore *sem, int val);

訊號量通常用於互斥模式,互斥體

靜態分配:

declare_mutex(name);   訊號量被初始化為1

declare_mutex_locked(name);     初始化為0

動態分配(執行時初始化):

void init_mutex(struct semaphore *sem);

void init_mutex_locked(struct semaphore *sem);

在linux世界中,p函式被稱為down,該函式減少訊號量的值,並在必要時一直等待。

down_interruptible:可中斷的版本,應該是我們始終使用的,它允許等待在某個訊號量上的使用者空間程序可被使用者中斷。

linux等價於v的函式是up:void up(struct semaphore *sem);呼叫up之後,呼叫者不再擁有該訊號量。

經常需要注意:如果在擁有乙個訊號量時發生錯誤,必須在將錯誤狀態返回給呼叫者之前釋放該訊號量。

讀取者/寫入者訊號量

訊號量對所有的呼叫者執行互斥,而不管每個執行緒到底想做什麼。但是許多任務可以劃分為兩種不同的工作型別:讀和寫。

允許多個併發的讀取者是可能的,這樣做可以大大提高效能。

struct rw_semaphore

completion

completion是一種輕量級的機制,它允許乙個執行緒告訴另乙個執行緒某個工作已經完成。

靜態:declare_completion(my_completion);

動態:struct completion my_completion;

init_completion(&my_completion);

等待completion:wait_for_completion(struct completion *c)

完成completion事件:complete(struct completion *c);

自旋鎖未完待續

併發與競態

linux是乙個多工的作業系統,在多個程序同時執行時,就有可能為了競爭同乙個資源發生堵塞。以下是解決的幾種方法 1 訊號量 declare mutex sem if down interruptible sem critical section up sem 2 完成量 declare comple...

Linux中的併發和競態

本帖大體上描述linux kernel為解決併發導致的競態所提供的核心api 主要是訊號量和自旋鎖 之間的區別,側重於使用方面。級的閱讀比較打算另開一貼。因為程式的併發執行而導致的競態是linux核心中乙個非常複雜的方面。對於裝置的驅動程式開發者而言,熟悉linux核心提供的併發互斥的處理機制相當重...

Linux中的併發和競態

本帖大體上描述linux kernel為解決併發導致的競態所提供的核心api 主要是訊號量和自旋鎖 之間的區別,側重於使用方面。級的閱讀比較打算另開一貼。因為程式的併發執行而導致的競態是linux核心中乙個非常複雜的方面。對於裝置的驅動程式開發者而言,熟悉linux核心提供的併發互斥的處理機制相當重...