c++ 自旋鎖,linux內核的自旋鎖spin_lock和互斥鎖mutex_lock

 2023-12-25 阅读 27 评论 0

摘要:訪問共享資源的代碼區域稱作臨界區。自旋鎖(spin_lock)和互斥鎖(mutex_lock)是保護內核臨界區的兩種基本機制。我們逐個分析。 自旋鎖可以確保在同時只有一個線程進入臨界區。其他想進入臨界區的線程必須不停地原地打轉,直到第1個線程釋放

訪問共享資源的代碼區域稱作臨界區。自旋鎖(spin_lock)和互斥鎖(mutex_lock)是保護內核臨界區的兩種基本機制。我們逐個分析。

自旋鎖可以確保在同時只有一個線程進入臨界區。其他想進入臨界區的線程必須不停地原地打轉,直到第1個線程釋放自旋鎖。注意:這里所說的線程不是內核線程,而是執行的線程。

理解自旋鎖最簡單的方法是把它作為一個變量看待,該變量把一個臨界區或者標記為“我當前在運行,請稍等一會”或者標記為“我當前不在運行,可以被使用” 。如果 A 執行單元首先進入例程,它將持有自旋鎖;當 B 執行單元試圖進入同一個例程時,將獲知自旋鎖已被持有,需等到 A 執行單元釋放后才能進入。

c++ 自旋鎖,驅動工程師應謹慎使用自旋鎖,而且在使用中還要特別注意如下幾個問題。
1、自旋鎖實際上是忙等鎖,當鎖不可用時,CPU 一直循環執行“測試并設置”該鎖直到可用而取得該鎖, CPU 在等待自旋鎖時不做任何有用的工作, 僅僅是等待。 因此, 只有在占用鎖的時間極短的情況下, 使用自旋鎖才是合理的。當臨界區很大或有共享設備的時候,需要較長時間占用鎖,使用自旋鎖會降低系統的性能。
2、自旋鎖可能導致系統死鎖。 引發這個問題最常見的情況是遞歸使用一個自旋鎖,即如果一個已經擁有某個自旋鎖的 CPU 想第二次獲得這個自旋鎖,則該 CPU 將死鎖。此外,如果進程獲得自旋鎖之后再阻塞,也有可能導致死鎖的發生。copy_from_user()、copy_to_user()和 kmalloc()等函數都有可能引起阻塞,因此在自旋鎖的占用期間不能調用這些函數。

自旋鎖的基本用法:

	//添加頭文件#include <linux/spinlock.h> //定義和初始化自旋鎖spinlockspinlock_t my_lock; //定義自旋鎖spinlockspin_lock_init(&my_lock); //初始化自旋鎖spinlockspin_lock(&my_lock); //獲取指定的自旋鎖spinlock,保護臨界區... /*臨界資源*/spin_unlock(&my_lock); //釋放指定的鎖spinlock

與自旋鎖不同的是,互斥鎖在進入一個被占用的臨界區之前不會原地打轉,而是使當前線程進入睡眠狀態。如果要等待的時間較長,互斥鎖比自旋鎖更合適,因為自旋鎖會消耗CPU資源。在使用互斥鎖的場合,多于2次進程切換時間都可被認為是長時間,因此一個互斥鎖會引起本線程睡眠,而當其被喚醒時,它需要被切換回來。

因此,在很多情況下,決定使用自旋鎖還是互斥鎖相對來說很容易:

linux自旋鎖和互斥鎖、(1) 如果臨界區需要睡眠,只能使用互斥鎖,因為在獲得自旋鎖后進行調度、搶占以及在等待隊列上睡眠都是非法的;

(2) 由于互斥鎖會在面臨競爭的情況下將當前線程置于睡眠狀態,因此,在中斷處理函數中,只能使用自旋鎖。

互斥鎖使用的基本方法:

	//添加頭文件#include <linux/mutex.h> //函數mutex_init()原型:void mutex_init(struct mutex *mutex);//定義和初始化互斥鎖mutexstruct mutex my_mutex;    //定義互斥鎖mutexmutex_init(&my_mutex);    //初始化互斥鎖mutex mutex_lock(&my_mutex);    //獲取互斥鎖mutex ... /*臨界資源*/mutex_unlock(&my_mutex); //釋放互斥鎖mutex

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/5/194848.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息