自旋鎖是用于保護短的代碼片段剩失,其中只包含少量C語句屈尼,因此會很快執(zhí)行完畢。大多數(shù)內(nèi)核數(shù)據(jù)結(jié)構(gòu)都有自身的自旋鎖拴孤,在處理結(jié)構(gòu)中的關(guān)鍵成員時脾歧,必須獲得相應(yīng)的自旋鎖。
定義自旋鎖
struct task_struct {
...
/* Protection of (de-)allocation: mm, files, fs, tty, keyrings */
spinlock_t alloc_lock;
...
1757 /*
1758 * Protects ->fs, ->files, ->mm, ->group_info, ->comm, keyring
1759 * subscriptions and synchronises with wait4(). Also used in procfs. Also
1760 * pins the final release of task.io_context. Also protects ->cpuset and
1761 * ->cgroup.subsys[].
1762 *
1763 * Nests both inside and outside of read_lock(&tasklist_lock).
1764 * It must not be nested with write_lock_irq(&tasklist_lock),
1765 * neither inside nor outside.
1766 */
初始化自旋鎖
./kernel/fork.c:1049: spin_lock_init(&p->alloc_lock);
獲取自旋鎖
1767 static inline void task_lock(struct task_struct *p)
1768 {
1769 spin_lock(&p->alloc_lock);
1770 }
釋放自旋鎖
1772 static inline void task_unlock(struct task_struct *p)
1773 {
1774 spin_unlock(&p->alloc_lock);
1775 }
自旋鎖的使用
在處理 task_struct 結(jié)構(gòu)中的 ptrace
/ files
/ active_mm
/ mm
/ flags
/ cgroups
/ io_context
等關(guān)鍵成員時乞巧,需要獲取 alloc_lock
自旋鎖涨椒。
void foo()
{
task_lock(current);
// 處理 task_struct 結(jié)構(gòu)的關(guān)鍵成員
task_unlock(current);
}
為什么這么多關(guān)鍵成員都使用同一個 alloc_lock
自旋鎖呢? 不會影響性能嗎绽媒? 為什么不使用不同的自旋鎖呢蚕冬?
個人理解:因為使用 alloc_lock
所保護的關(guān)鍵成員操作并不頻繁,而且操作的時間點并不集中是辕,所以不會影響性能囤热。
自旋鎖用來在多處理器的環(huán)境下保護數(shù)據(jù)。如果內(nèi)核發(fā)現(xiàn)數(shù)據(jù)未鎖获三,就獲取鎖并運行旁蔼;如果數(shù)據(jù)已鎖,就一直旋轉(zhuǎn)疙教,其實是一直反復(fù)執(zhí)行一條指令棺聊。之所以說自旋鎖用在多處理器環(huán)境,是因為在單處理器環(huán)境(非搶占式內(nèi)核)下贞谓,自旋鎖其實不起作用限佩。在單處理器搶占式內(nèi)核的情況下,自旋鎖起到禁止搶占的作用裸弦。
因為被自旋鎖鎖著的進程一直旋轉(zhuǎn)祟同,而不是睡眠,所以自旋鎖可以用在中斷等禁止睡眠的場景理疙。
spin_lock 會考慮下面兩種情況:
- 如果內(nèi)核中其他地方尚未獲得 lock晕城,則有當(dāng)前處理器獲取。其它處理器不能再進入 lock 保護的代碼范圍窖贤。
- 如果 lock 已經(jīng)由另一個處理器獲得砖顷,spin_lock 進入一個無限循環(huán),重復(fù)地檢查 lock 是否已經(jīng)由 spin_unlock 釋放(自旋鎖因此得名)赃梧。如果已經(jīng)釋放滤蝠,則獲得 lock ,并進入臨界區(qū)槽奕。
在使用自旋鎖時必須要注意下面兩點几睛。
- 如果獲得鎖之后不釋放,系統(tǒng)將變的不可用粤攒。所有的處理器(包括獲得鎖的在內(nèi))所森,遲早需要進入對應(yīng)的臨界區(qū)囱持。它們會進入無限循環(huán)等待鎖釋放,但等不到焕济。便產(chǎn)生了死鎖纷妆。
- 自旋鎖絕不應(yīng)該長期持有,因為所有等待釋放鎖的處理器都處于不可用狀態(tài)晴弃,無法用于其他工作(信號量的情形有所不同)掩幢。