旗標(biāo)機(jī)制給予 scull 一個工具, 可以在存取 scull_dev 數(shù)據(jù)結(jié)構(gòu)時用來避免競爭情況. 但是正確使用這個工具是我們的責(zé)任. 正確使用加鎖原語的關(guān)鍵是嚴(yán)密地指定要保護(hù)哪個 資源并且確認(rèn)每個對這些資源的存取都使用了正確的加鎖方法. 在我們的例子驅(qū)動中, 感 興趣的所有東西都包含在 scull_dev 結(jié)構(gòu)里面, 因此它是我們的加鎖體制的邏輯范圍. 讓我們在看看這個結(jié)構(gòu): struct scull_dev { struct scull_qset *data; /* Pointer to first quantum set */ int quantum; /* the current quantum size */ int qset; /* the current array size */ unsigned long size; /* amount of data stored here */ unsigned int access_key; /* used by sculluid and scullpriv */ struct semaphore sem; /* mutual exclusion semaphore */ struct cdev cdev; /* Char device structure */ }; ? 到結(jié)構(gòu)的底部是一個稱為 sem 的成員, 當(dāng)然, 它是我們的旗標(biāo). 我們已經(jīng)選擇為每個虛 擬 scull 設(shè)備使用單獨(dú)的旗標(biāo). 使用一個單個的全局的旗標(biāo)也可能會是同樣正確. 通常 各種 scull 設(shè)備不共享資源, 然而, 并且沒有理由使一個進(jìn)程等待, 而另一個進(jìn)程在使 用不同 scull 設(shè)備. 不同設(shè)備使用單獨(dú)的旗標(biāo)允許并行進(jìn)行對不同設(shè)備的操作, 因此, 提高了性能. 旗標(biāo)在使用前必須初始化. scull 在加載時進(jìn)行這個初始化, 在這個循環(huán)中: for (i = 0; i < scull_nr_devs; i ) { scull_devices[i].quantum = scull_quantum; scull_devices[i].qset = scull_qset; init_MUTEX(&scull_devices[i].sem); scull_setup_cdev(&scull_devices[i], i); } ? 注意, 旗標(biāo)必須在 scull 設(shè)備對系統(tǒng)其他部分可用前初始化. 因此, init_MUTEX 在 scull_setup_cdev 前被調(diào)用. 以相反的次序進(jìn)行這個操作可能產(chǎn)生一個競爭情況, 旗標(biāo) 可能在它準(zhǔn)備好之前被存取. ? 下一步, 我們必須瀏覽代碼, 并且確認(rèn)在沒有持有旗標(biāo)時沒有對 scull_dev 數(shù)據(jù)結(jié)構(gòu)的 存取. 因此, 例如, scull_write 以這個代碼開始: ? if (down_interruptible(&dev->sem)) ? return -ERESTARTSYS; ? 注意對 down_interruptible 返回值的檢查; 如果它返回非零, 操作被打斷了. 在這個情 況下通常要做的是返回 -ERESTARTSYS. 看到這個返回值后, 內(nèi)核的高層要么從頭重啟這 個調(diào)用要么返回這個錯誤給用戶. 如果你返回 -ERESTARTSYS, 你必須首先恢復(fù)任何用戶 可見的已經(jīng)做了的改變, 以保證當(dāng)重試系統(tǒng)調(diào)用時正確的事情發(fā)生. 如果你不能以這個方 式恢復(fù), 你應(yīng)當(dāng)替之返回 -EINTR. ? scull_write 必須釋放旗標(biāo), 不管它是否能夠成功進(jìn)行它的其他任務(wù). 如果事事都順利, 執(zhí)行落到這個函數(shù)的最后幾行: ? out: up(&dev->sem); return retval; ? 這個代碼釋放旗標(biāo)并且返回任何需要的狀態(tài). 在 scull_write 中有幾個地方可能會出錯; 這些地方包括內(nèi)存分配失敗或者在試圖從用戶空間拷貝數(shù)據(jù)時出錯. 在這些情況中, 代碼 進(jìn)行了一個 goto out, 以確保進(jìn)行正確的清理. 來源:https://www./content-3-304101.html |
|