5.2. 并發(fā)和它的管理

2018-02-24 15:49 更新

5.2.?并發(fā)和它的管理

在現(xiàn)代 Linux 系統(tǒng), 有非常多的并發(fā)源, 并且因此而來(lái)的可能競(jìng)爭(zhēng)情況. 多個(gè)用戶(hù)空間進(jìn)程在運(yùn)行, 它們可能以令人驚訝的方式組合存取你的代碼. SMP 系統(tǒng)能夠同時(shí)在不同處理器上執(zhí)行你的代碼. 內(nèi)核代碼是可搶占的; 你的驅(qū)動(dòng)代碼可能在任何時(shí)間失去處理器, 代替它的進(jìn)程可能也在你的驅(qū)動(dòng)中運(yùn)行. 設(shè)備中斷是能夠?qū)е履愕拇a并發(fā)執(zhí)行的異步事件. 內(nèi)核也提供各種延遲代碼執(zhí)行的機(jī)制, 例如 workqueue, tasklet, 以及定時(shí)器, 這些能夠使你的代碼在任何時(shí)間以一種與當(dāng)前進(jìn)程在做的事情無(wú)關(guān)的方式運(yùn)行. 在現(xiàn)代的, 熱插拔的世界中, 你的設(shè)備可能在你使用它們的時(shí)候輕易地消失.

避免競(jìng)爭(zhēng)情況可能是一個(gè)令人害怕的工作. 在一個(gè)任何時(shí)候可能發(fā)生任何事的世界, 驅(qū)動(dòng)程序員如何避免產(chǎn)生絕對(duì)的混亂? 事實(shí)證明, 大部分競(jìng)爭(zhēng)情況可以避免, 通過(guò)一些想法, 內(nèi)核并發(fā)控制原語(yǔ), 以及幾個(gè)基本原則的應(yīng)用. 我們會(huì)先從原則開(kāi)始, 接著進(jìn)入如何使用它們的細(xì)節(jié)中

競(jìng)爭(zhēng)情況來(lái)自對(duì)資源的共享存取的結(jié)果. 當(dāng) 2 個(gè)執(zhí)行的線路[17]有機(jī)會(huì)操作同一個(gè)數(shù)據(jù)結(jié)構(gòu)(或者硬件資源), 混合的可能性就一直存在. 因此第一個(gè)經(jīng)驗(yàn)法則是在你設(shè)計(jì)驅(qū)動(dòng)時(shí)在任何可能的時(shí)候記住避免共享的資源. 如果沒(méi)有并發(fā)存取, 就沒(méi)有競(jìng)爭(zhēng)情況. 因此小心編寫(xiě)的內(nèi)核代碼應(yīng)當(dāng)有最小的共享. 這個(gè)想法的最明顯應(yīng)用是避免使用全局變量. 如果你將一個(gè)資源放在多個(gè)執(zhí)行線路能夠找到它的地方, 應(yīng)當(dāng)有一個(gè)很強(qiáng)的理由這樣做.

事實(shí)是, 然而, 這樣的共享常常是需要的. 硬件資源是, 由于它們的特性, 共享的, 軟件資源也必須常常共享給多個(gè)線程. 也要記住全局變量遠(yuǎn)遠(yuǎn)不是共享數(shù)據(jù)的唯一方式; 任何時(shí)候你的代碼傳遞一個(gè)指針給內(nèi)核的其他部分, 潛在地它創(chuàng)造了一個(gè)新的共享情形. 共享是生活的事實(shí).

這是資源共享的硬規(guī)則: 任何時(shí)候一個(gè)硬件或軟件資源被超出一個(gè)單個(gè)執(zhí)行線程共享, 并且可能存在一個(gè)線程看到那個(gè)資源的不一致時(shí), 你必須明確地管理對(duì)那個(gè)資源的存取. 在上面的 scull 例子, 這個(gè)情況在進(jìn)程 B 看來(lái)是不一致的; 不知道進(jìn)程 A 已經(jīng)為( 共享的 ) 設(shè)備分配了內(nèi)存, 它做它自己的分配并且覆蓋了 A 的工作. 在這個(gè)例子里, 我們必須控制對(duì) scull 數(shù)據(jù)結(jié)構(gòu)的存取. 我們需要安排, 這樣代碼或者看到內(nèi)存已經(jīng)分配了, 或者知道沒(méi)有內(nèi)存已經(jīng)或者將要被其他人分配. 存取管理的常用技術(shù)是加鎖或者互斥 -- 確保在任何時(shí)間只有一個(gè)執(zhí)行線程可以操作一個(gè)共享資源. 本章剩下的大部分將專(zhuān)門(mén)介紹加鎖.

然而, 首先, 我們必須簡(jiǎn)短考慮一下另一個(gè)重要規(guī)則. 當(dāng)內(nèi)核代碼創(chuàng)建一個(gè)會(huì)被內(nèi)核其他部分共享的對(duì)象時(shí), 這個(gè)對(duì)象必須一直存在(并且功能正常)到它知道沒(méi)有對(duì)它的外部引用存在為止. scull 使它的設(shè)備可用的瞬間, 它必須準(zhǔn)備好處理對(duì)那些設(shè)備的請(qǐng)求. 并且 scull 必須一直能夠處理對(duì)它的設(shè)備的請(qǐng)求直到它知道沒(méi)有對(duì)這些設(shè)備的引用(例如打開(kāi)的用戶(hù)空間文件)存在. 2 個(gè)要求出自這個(gè)規(guī)則: 除非它處于可以正確工作的狀態(tài), 不能有對(duì)象能對(duì)內(nèi)核可用, 對(duì)這樣的對(duì)象的引用必須被跟蹤. 在大部分情況下, 你將發(fā)現(xiàn)內(nèi)核為你處理引用計(jì)數(shù), 但是常常有例外.

遵照上面的規(guī)則需要計(jì)劃和對(duì)細(xì)節(jié)小心注意. 容易被對(duì)資源的并發(fā)存取而吃驚, 你事先并沒(méi)有認(rèn)識(shí)到被共享. 通過(guò)一些努力, 然而, 大部分競(jìng)爭(zhēng)情況能夠在它們咬到你或者你的用戶(hù)前被消滅.

[17] 本章的意圖, 一個(gè)執(zhí)行"線程"是任何運(yùn)行代碼的上下文. 每個(gè)進(jìn)程顯然是一個(gè)執(zhí)行線程, 但是一個(gè)中斷處理也是, 或者其他響應(yīng)一個(gè)異步內(nèi)核事件的代碼.

以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)