2011-01-21 103 views
6

我在閱讀「Linux設備驅動程序第3版」,關於併發性和競爭條件的章節。有一個我不完全明白的例子。他們正在討論內核編程中的一種常見模式,當需要在當前線程之外啓動活動(例如,新的內核線程或用戶進程,請求現有進程或基於硬件的操作)時,請等待該活動完成。不是非常有效的解決方案的例子是:Linux內核互斥體

struct semaphore sem; 
init_MUTEX_LOCKED(&sem); 
start_external_task(&sem); 
down(&sem); 

然後,他們認爲外部任務調用(& SEM)時,它的工作就完成了。

我不明白爲什麼我們不能這樣來做:

struct semaphore sem; 
down(&sem); 
start_external_task(&sem); 

爲什麼是必要的鎖定狀態,以創建互斥量,然後獲得任務之後互斥體已經開始了嗎?

期待您的迴音!謝謝。

回答

10

當您調用down()時,您的線程將阻塞,直到另一個線程發出信號指示信號。由於另一個線程尚未啓動,線程將無限期阻塞。這就是爲什麼你需要先啓動線程,然後調用down()來阻塞,直到線程完成。

如果線程在調用down()之前完成,那沒問題,因爲信號量將被髮信號,down()將簡單地清除信號並返回。

+6

+1,但我認爲使用術語`semaphore`而不是`mutex`會更好。 SEMAPHORE:可以通過任何線程上/下。 MUTEX:擁有所有權,只有鎖擁有者線程可以啓用互斥鎖。在這種情況下,我們需要使用信號量,因爲它的目的是線程之間的通信... – Vojta 2011-01-21 11:06:39

3

在第一個示例中,down(& sem)將等待external_task調用(& sem)並有效地暫停主線程,直到任務完成。 在你的代碼向下()將永遠鎖定主線程,因爲沒有任務尚未調用()

1

召喚:

init_MUTEX_LOCKED(&sem); 

中創建初始化爲0「互斥模式」的新信號。這意味着呼叫down()將被阻止。一個相應的呼叫:

init_MUTEX(&sem); 

將創建初始化爲1

在你初始化信號爲0,第1例的旗語,您創建external_task和你打電話down()阻塞,直到你的任務調用up()

在第二個例子中,你不初始化您的旗語,叫down()阻止執行,並沒有external_task運行的可調用up()解除阻止你。創建external_task的調用因此從未達到。

順便說一下,在內核版本2.6.37中,init_MUTEX_LOCKED初始化信號量的過程已被刪除。