新聞中心
在Linux系統(tǒng)中,死鎖是一種常見的現(xiàn)象。當(dāng)不同的進(jìn)程或線程同時(shí)請(qǐng)求相同資源時(shí),可能會(huì)造成死鎖。本文將介紹Linux系統(tǒng)下常見的死鎖現(xiàn)象以及解決方法。

創(chuàng)新互聯(lián)專業(yè)為企業(yè)提供婺源網(wǎng)站建設(shè)、婺源做網(wǎng)站、婺源網(wǎng)站設(shè)計(jì)、婺源網(wǎng)站制作等企業(yè)網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)與制作、婺源企業(yè)網(wǎng)站模板建站服務(wù),10多年婺源做網(wǎng)站經(jīng)驗(yàn),不只是建網(wǎng)站,更提供有價(jià)值的思路和整體網(wǎng)絡(luò)服務(wù)。
一、死鎖現(xiàn)象
1.資源競(jìng)爭(zhēng)
進(jìn)程或線程之間競(jìng)爭(zhēng)同一資源,例如同一文件或同一設(shè)備。
2.互斥
進(jìn)程或線程只能以互斥的方式訪問某些資源。當(dāng)多個(gè)進(jìn)程或線程都需要這些資源時(shí),可能會(huì)發(fā)生死鎖。
3.占用且等待
進(jìn)程或線程占用了某些資源,并且等待其他資源,而這些資源已經(jīng)被其他進(jìn)程占用。
4.循環(huán)等待
當(dāng)兩個(gè)或多個(gè)進(jìn)程或線程相互等待對(duì)方所持有的資源時(shí),會(huì)發(fā)生循環(huán)等待。
二、死鎖解決方法
1.避免死鎖
避免死鎖是更好的解決方法。在編程中,應(yīng)該避免不必要的資源競(jìng)爭(zhēng)和互斥,盡可能減少進(jìn)程或線程對(duì)資源的需要,并確保每次只鎖定必要的資源。此外,應(yīng)該限制資源的占用時(shí)間和優(yōu)先級(jí)。
2.檢測(cè)和恢復(fù)
當(dāng)死鎖發(fā)生時(shí),可以通過檢測(cè)和恢復(fù)的方式解決。檢測(cè)死鎖可以通過算法來實(shí)現(xiàn),最常用的是銀行家算法。銀行家算法可以檢測(cè)系統(tǒng)中是否存在死鎖,并且可以通過釋放一些占用資源的進(jìn)程或線程來解除死鎖。此外,可以使用死鎖恢復(fù)策略來避免死鎖的出現(xiàn)。
3.破壞死鎖
可以通過破壞死鎖中的任一條件來解決死鎖??梢葬尫乓恍┻M(jìn)程或線程所占用的資源,以期待其他進(jìn)程或線程可以接收這些資源??梢該屨寄承┻M(jìn)程或線程所持有的資源,以便其他進(jìn)程或線程可以訪問這些資源??梢猿蜂N某些進(jìn)程或線程,以釋放資源,并盡可能減少死鎖的存在。
三、代碼示例
以下是一個(gè)簡單的代碼示例,演示如何使用互斥鎖避免死鎖。
“`c
#include
#include
#include
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
void *thread1(void *arg) {
pthread_mutex_lock(&mutex1);
printf(“Thread 1 locked mutex 1\n”);
sleep(1);
pthread_mutex_lock(&mutex2);
printf(“Thread 1 locked mutex 2\n”);
pthread_mutex_unlock(&mutex2);
pthread_mutex_unlock(&mutex1);
return NULL;
}
void *thread2(void *arg) {
pthread_mutex_lock(&mutex2);
printf(“Thread 2 locked mutex 2\n”);
sleep(1);
pthread_mutex_lock(&mutex1);
printf(“Thread 2 locked mutex 1\n”);
pthread_mutex_unlock(&mutex1);
pthread_mutex_unlock(&mutex2);
return NULL;
}
int mn() {
pthread_t t1, t2;
pthread_create(&t1, NULL, thread1, NULL);
pthread_create(&t2, NULL, thread2, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
return 0;
}
“`
在以上示例中,兩個(gè)線程都需要訪問兩個(gè)互斥鎖。為了避免死鎖,線程1首先鎖定mutex1,然后嘗試鎖定mutex2。當(dāng)線程2嘗試鎖定mutex2時(shí),由于mutex2已被線程1鎖定,線程2只能等待。當(dāng)線程1釋放mutex2并解鎖mutex1后,線程2可以鎖定mutex2,然后繼續(xù)執(zhí)行。這種方法可以避免死鎖的出現(xiàn)。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
linux rcu鎖問題怎么查
眾所周知,為了保護(hù)共享數(shù)空運(yùn)據(jù),需要一些同步機(jī)制,如自旋鎖(spinlock),讀寫鎖(rwlock),它們使用起來非常簡單,而且是一種很有效的同步機(jī)制,在UNIX系統(tǒng)和Linux系統(tǒng)中得到了廣泛的使用。但是隨著計(jì)算機(jī)硬件的快速發(fā)展,獲得這種鎖的開銷相對(duì)于CPU的速度在成倍地增加,原因很簡單,CPU的速度與訪問內(nèi)存的速度差距越來越大,而這種鎖使用了原子操作指令,它需要原子地訪問內(nèi)存,也就說獲得鎖的開銷與訪存速度相關(guān),另外在大部分非x86架構(gòu)上獲取鎖使用了內(nèi)存柵(Memory Barrier),這會(huì)導(dǎo)致處理器流水線停滯或刷新,因此它的開銷相對(duì)于CPU速度而言就越來越大。
在操作系統(tǒng)中,數(shù)據(jù)一致性訪問是一個(gè)非常重要的部分,通常我們可以采用鎖機(jī)制實(shí)現(xiàn)數(shù)據(jù)的一致性訪問。例如,semaphore、spinlock機(jī)制,在訪問共享數(shù)據(jù)時(shí),首先訪問鎖資源,在獲取鎖資源的前提下才能實(shí)現(xiàn)數(shù)據(jù)的訪問。這種原理很簡單,根本的思想就是在訪問臨界資源時(shí),首先訪問一個(gè)全局的變量(鎖),通過全局變量的狀態(tài)來控制線程對(duì)臨界資源的訪問。但是,這種思想是需要硬件支持的,硬件需要配合實(shí)現(xiàn)全局變量(鎖)的讀-修改-寫,現(xiàn)代CPU都會(huì)提供這樣的原子化指令。采用鎖機(jī)制實(shí)現(xiàn)數(shù)據(jù)訪問的一致性存在如下兩個(gè)問題:
1、 效率問題。鎖機(jī)制的實(shí)現(xiàn)需要對(duì)內(nèi)存的原子化訪問,這種訪問操作會(huì)破壞流水線操作,降低了流水線效率。這是影響性能的一個(gè)因素。另外,在采用讀寫鎖機(jī)制的情況下,寫鎖是排他鎖,無法實(shí)現(xiàn)寫鎖與讀鎖的并發(fā)操作,在某些應(yīng)用下回降低性能。
2、 擴(kuò)展性問題。當(dāng)系統(tǒng)中CPU數(shù)量增多的時(shí)候,采用鎖機(jī)制實(shí)現(xiàn)數(shù)據(jù)的同步訪問效率偏低。并且隨著CPU數(shù)量的增多,效率降低,由此可見鎖機(jī)制實(shí)現(xiàn)的數(shù)據(jù)一致性訪問擴(kuò)展性差。
為了解決上述問題,Linux中引進(jìn)了RCU機(jī)制。該機(jī)制在多CPU的平臺(tái)上比較適用,對(duì)于讀多寫少的應(yīng)用尤其適游悶用。RCU的思路實(shí)際上很簡單,下面對(duì)其進(jìn)行描述:
1、對(duì)于讀操作,可以直接對(duì)共享資源進(jìn)行訪問,但是前提是需要CPU支持訪存操作的原子化,現(xiàn)代CPU對(duì)這一點(diǎn)都做了保證。但是RCU的讀操作上下文是不可搶占的(這一點(diǎn)在下面解釋),所以讀訪問共享資源時(shí)可以采用read_rcu_lock(),該函數(shù)的工作是停止搶占。
2、對(duì)于寫操作,其需要將原來的老數(shù)據(jù)作一次備份(copy),然后對(duì)備份數(shù)據(jù)進(jìn)行修改,修改完畢之后再用新數(shù)據(jù)更新老數(shù)據(jù),更新老數(shù)據(jù)時(shí)采用了rcu_assign_pointer()宏,在該函數(shù)中首先屏障一下memory,然后修改老數(shù)據(jù)。這個(gè)操作完成之后,需要進(jìn)行老數(shù)據(jù)資源的回收。操作線程向系統(tǒng)注冊(cè)回收方法,等待回收。采用數(shù)據(jù)備份的方法可以實(shí)現(xiàn)讀者與寫者之間的并發(fā)操作,但是不能解決多個(gè)寫著之間的同步,所以當(dāng)存在多個(gè)寫者時(shí),需要通過鎖機(jī)制對(duì)其進(jìn)行互斥,也就是在同一時(shí)刻只能存在一個(gè)寫者。
3、在RCU機(jī)制中存在一個(gè)垃圾回收的daemon,當(dāng)共享資源被update之后,可以采用該daemon實(shí)現(xiàn)老數(shù)據(jù)資源的回收?;厥諘r(shí)間點(diǎn)就是在update之前的所有的讀者全部退出。由此可見寫者在update之后是需要睡眠等待的,需斗磨梁要等待讀者完成操作,如果在這個(gè)時(shí)刻讀者被搶占或者睡眠,那么很可能會(huì)導(dǎo)致系統(tǒng)死鎖。因?yàn)榇藭r(shí)寫者在等待讀者,讀者被搶占或者睡眠,如果正在運(yùn)行的線程需要訪問讀者和寫者已經(jīng)占用的資源,那么死鎖的條件就很有可能形成了。
請(qǐng)教linux下用戶態(tài)進(jìn)程調(diào)度問題
在進(jìn)行Linux系統(tǒng)操作的時(shí)候,有時(shí)候會(huì)遇到一次用戶態(tài)進(jìn)程死循環(huán),即系統(tǒng)反應(yīng)遲鈍、進(jìn)程掛死等問題,那么遇到這些問題又該如何解決呢?下面小編就給大家介紹下一次用戶態(tài)進(jìn)程死循環(huán)的問題該如何處瞎顫理。
Linux下如何處理一次用戶態(tài)進(jìn)程死循環(huán)問題
1、問題現(xiàn)象
業(yè)務(wù)進(jìn)程(用戶態(tài)多線程程序)掛死,操作系統(tǒng)反應(yīng)遲鈍,系統(tǒng)日志沒有任何異常。從進(jìn)程的內(nèi)核態(tài)堆??矗此扑芯€程都卡在了內(nèi)核態(tài)的如下堆棧流程中:
?。踨oot@vmc116 ~]# cat /proc/27007/task/11825/stack
?。邸秄fffffff8100baf6》] retint_careful+0x14/0x32
?。邸秄fffffffffffffff》] 0xffffffffffffffff
2、喊兄問題分析
1)內(nèi)核堆棧分析
從內(nèi)核堆???,所有進(jìn)程都阻塞在 retint_careful上,這個(gè)是中斷返回過程中的流程,代碼(匯編)如下:
entry_64.S
代碼如下:
ret_from_intr:
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
decl PER_CPU_VAR(irq_count)
/* Restore saved previous stack */
popq %rsi
CFI_DEF_CFA rsi,SS+8-RBP /* reg/off reset after def_cfa_expr */
leaq ARGOFFSET-RBP(%rsi), %rsp
CFI_DEF_CFA_REGISTER rsp
CFI_ADJUST_CFA_OFFSET RBP-ARGOFFSET
。
retint_careful:
CFI_RESTORE_STATE
bt $TIF_NEED_RESCHED,%edx
jnc retint_signal
TRACE_IRQS_ON
ENABLE_INTERRUPTS(CLBR_NONE)
pushq_cfi %rdi
磨滲敗 SCHEDULE_USER
popq_cfi %rdi
GET_THREAD_INFO(%rcx)
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
jmp retint_check
這其實(shí)是用戶態(tài)進(jìn)程在用戶態(tài)被中斷打斷后,從中斷返回的流程,結(jié)合retint_careful+0x14/0x32,進(jìn)行反匯編,可以確認(rèn)阻塞的點(diǎn)其實(shí)就在
SCHEDULE_USER
這其實(shí)就是調(diào)用schedule()進(jìn)行調(diào)度,也就是說當(dāng)進(jìn)程走到中斷返回的流程中時(shí),發(fā)現(xiàn)需要調(diào)度(設(shè)置了TIF_NEED_RESCHED),于是在這里發(fā)生了調(diào)度。
有一個(gè)疑問:為什么在堆棧中看不到schedule()這一級(jí)的棧幀呢?
因?yàn)檫@里是匯編直接調(diào)用的,沒有進(jìn)行相關(guān)棧幀壓棧和上下文保存操作。
2)進(jìn)行狀態(tài)信息分析
從top命令結(jié)果看,相關(guān)線程實(shí)際一直處于R狀態(tài),CPU幾乎完全耗盡,而且絕大部分都消耗在用戶態(tài):
?。踨oot@vmc116 ~]# top
top – 09:42:23 up 16 days, 2:21, 23 users, load average: 84.08, 84.30, 83.62
Tasks: 1037 total, 85 running, 952 sleeping, 0 stopped, 0 zombie
Cpu(s): 97.6%us, 2.2%sy, 0.2%ni, 0.0%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem:k total,k used,k free,k buffers
Swap:k total, 38644k used,k free,k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
rootm 163m 14m R 10.2 0.5 321:06.17 z_itask_templat
rootm 163m 14m R 10.2 0.5 296:23.37 z_itask_templat
rootm 163m 14m R 10.2 0.5 337:57.26 z_itask_templat
rootm 163m 14m R 10.2 0.5 327:31.93 z_itask_templat
rootm 163m 14m R 10.2 0.5 306:49.44 z_itask_templat
rootm 163m 14m R 10.2 0.5 310:47.41 z_itask_templat
rootm 163m 14m R 10.2 0.5 283:03.37 z_itask_templat
rootm 163m 14m R 10.2 0.5 283:49.67 z_itask_templat
rootm 163m 14m R 10.2 0.5 261:24.46 z_itask_templat
rootm 163m 14m R 10.2 0.5 150:24.53 z_itask_templat
rootm 163m 14m R 10.2 0.5 100:26.77 z_itask_templat
rootm 163m 14m R 9.9 0.5 337:18.77 z_itask_templat
rootm 163m 14m R 9.9 0.5 314:24.17 z_itask_templat
rootm 163m 14m R 9.9 0.5 336:32.78 z_itask_templat
rootm 163m 14m R 9.9 0.5 338:55.08 z_itask_templat
rootm 163m 14m R 9.9 0.5 306:46.08 z_itask_templat
rootm 163m 14m R 9.9 0.5 316:49.51 z_itask_templat
。
3)進(jìn)程調(diào)度信息
從相關(guān)線程的調(diào)度信息看:
?。踨oot@vmc116 ~]# cat /proc/27007/task/11825/schedstat
?。踨oot@vmc116 ~]# cat /proc/27007/task/11825/schedstat
?。踨oot@vmc116 ~]# cat /proc/27007/task/11825/schedstat
[root@vmc116 ~]# cat /proc/27007/task/11825/schedstat
?。踨oot@vmc116 ~]# cat /proc/27007/task/11825/schedstat
發(fā)現(xiàn)相關(guān)線程的調(diào)度統(tǒng)計(jì)一直在增加,說明相關(guān)線程一直是在被調(diào)度運(yùn)行的,結(jié)合其狀態(tài)也一直是R,推測(cè)很可能在用戶態(tài)發(fā)生了死循環(huán)(或者非睡眠死鎖)。
這里又有問題:為什么從top看每個(gè)線程的CPU占用率只有10%左右,而不是通??吹降乃姥h(huán)進(jìn)程導(dǎo)致的100%的占用率?
因?yàn)榫€程數(shù)很多,而且優(yōu)先級(jí)都一樣,根據(jù)CFS調(diào)度算法,會(huì)平均分配時(shí)間片,不會(huì)讓其中一個(gè)線程獨(dú)占CPU。結(jié)果為多個(gè)線程間輪流調(diào)度,消耗掉了所有的cpu。
另一個(gè)問題:為什么這種情況下,內(nèi)核沒有檢測(cè)到softlockup?
因?yàn)闃I(yè)務(wù)進(jìn)程的優(yōu)先級(jí)不高,不會(huì)影響watchdog內(nèi)核線程(更高優(yōu)先級(jí)的實(shí)時(shí)線程)的調(diào)度,所以不會(huì)產(chǎn)生softlockup的情況。
再一個(gè)問題:為什么每次查看線程堆棧時(shí),總是阻塞在retint_careful,而不是其它地方?
因?yàn)檫@里(中斷返回的時(shí)候)正是調(diào)度的時(shí)機(jī)點(diǎn),在其它時(shí)間點(diǎn)不能發(fā)生調(diào)度(不考慮其它情況~),而我們查看線程堆棧的行為,也必須依賴于進(jìn)程調(diào)度,所以我們每次查看堆棧時(shí),正是查看堆棧的進(jìn)程(cat命令)得到調(diào)度的時(shí)候,這時(shí)正是中斷返回的時(shí)候,所以正好看到的阻塞點(diǎn)為retint_careful。
4)用戶態(tài)分析
從上面的分析看,推測(cè)應(yīng)該是用戶態(tài)發(fā)生了死鎖。
用戶態(tài)確認(rèn)方法:
部署debug信息,然后gdb attach相關(guān)進(jìn)程,確認(rèn)堆棧,并結(jié)合代碼邏輯分析。
最終確認(rèn)該問題確為用戶態(tài)進(jìn)程中產(chǎn)生了死循環(huán)。
我在linux中安裝rpm包時(shí)候遇到麻煩,很有趣,類似我們學(xué)數(shù)據(jù)庫oracle中的“死鎖”問題,
說明這些都是相互有依賴關(guān)系的軟件包,只需要一起同時(shí)安裝即可。
方殲滾行法1:
rpm -ivh elfutils-libelf-devel-0.137-3.el5.x86_64.rmp elfutils-libelf-devel-static-0.137-3.el5.x86_64.rpm
如果還不能,請(qǐng)加備拿–nodeps,如果還不能裝,請(qǐng)加氏嘩–force
方法2:
yum install elfutils-libelf-devel*
可以使用斗粗喊–nodeps參數(shù)安裝,作用是忽略空野依賴凳粗關(guān)系
rpm -ivh –nodeps elfutils-libelf-devel-static-x86_64.rpm
我也攔則是搞了一個(gè)晚上都不行,偶然間試鎮(zhèn)衡衡了一御做下 yum install elfutils-libelf-devel* 結(jié)果提示可能為dnf插件,于是試了一下 dnf install elfutils-libelf-devel* 結(jié)果安裝成功?。?我是fedora27。
關(guān)于linux 死鎖現(xiàn)象的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
四川成都云服務(wù)器租用托管【創(chuàng)新互聯(lián)】提供各地服務(wù)器租用,電信服務(wù)器托管、移動(dòng)服務(wù)器托管、聯(lián)通服務(wù)器托管,云服務(wù)器虛擬主機(jī)租用。成都機(jī)房托管咨詢:13518219792
創(chuàng)新互聯(lián)(www.cdcxhl.com)擁有10多年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開發(fā)經(jīng)驗(yàn)、開啟建站+互聯(lián)網(wǎng)銷售服務(wù),與企業(yè)客戶共同成長,共創(chuàng)價(jià)值。
網(wǎng)頁名稱:Linux系統(tǒng)下常見的死鎖現(xiàn)象及解決方法(linux死鎖現(xiàn)象)
URL地址:http://www.fisionsoft.com.cn/article/djepgjh.html


咨詢
建站咨詢
