日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > linux >内容正文

linux

[Linux]继续探究mysleep函数(竞态条件)

發(fā)布時間:2023/11/30 linux 45 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Linux]继续探究mysleep函数(竞态条件) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

之前我們探究過mysleep的簡單用法,我們實現(xiàn)的代碼是這樣的:

#include<stdio.h> #include<signal.h>void myhandler(int sig) {}unsigned int mysleep(unsigned int timeout) {struct sigaction act,oact;act.sa_handler = myhandler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigaction(SIGALRM,&act,&oact); //信號注冊函數(shù)alarm(timeout); //鬧鐘timeout秒后響pause(); //掛起等待unsigned int ret = alarm(0); //清空鬧鐘sigaction(SIGALRM,&oact,NULL);return ret; }int main() {printf("ready sleeping!\n");mysleep(3);printf("i am waking!\n");return 0; }

我們首先注冊了捕捉信號的函數(shù),信號為SIGALRM,然后調(diào)用了alarm函數(shù)來設(shè)置鬧鐘,此時pause來掛起等待,然后內(nèi)核切換到別的進(jìn)程運行,在timeout秒后鬧鐘產(chǎn)生SIGALRM信號,從內(nèi)核態(tài)到用戶態(tài)的過程中,收到用戶自定義的處理函數(shù),就在用戶態(tài)處理函數(shù),進(jìn)入處理函數(shù)myhandler時,SIGALRM信號會被自動屏蔽,當(dāng)處理完函數(shù)后,自動解除屏蔽,進(jìn)入到內(nèi)核態(tài)執(zhí)行系統(tǒng)調(diào)用,最后切換到用戶態(tài)執(zhí)行主函數(shù)控制邏輯。

這里存在一個問題,比如剛剛說的alarm函數(shù)調(diào)用完成后,pause掛起等待,當(dāng)把所有的邏輯都處理完成alarm返回時,進(jìn)入用戶態(tài)繼續(xù)pause,是不是沒有任何意義呢。還有一點,我們不知道pause掛起等待是在alarm函數(shù)之內(nèi)還是執(zhí)行后調(diào)用的,這就出現(xiàn)了異步情況,我們稱這種現(xiàn)象為競態(tài)條件。

我們?nèi)绾谓鉀Q這類問題呢。。我們試著將SIGALRM信號屏蔽起來,當(dāng)執(zhí)行完alarm函數(shù)后再自動解除屏蔽。這樣就保證是在alarm函數(shù)執(zhí)行到時間后掛起的狀態(tài)。但是還有一種可能是當(dāng)解除屏蔽之后還有可能使SIGALRM遞達(dá),因此這種方法還是有缺陷的。我們只能用原子性的操作來避免這種問題的出現(xiàn)。

這時又引出了一個函數(shù):sigsuspend包含了pause的掛起等待功能,同時解決了競態(tài)條件的問題(與exec和pause一樣,沒有成功的返回值)

#include <signal.h> int sigsuspend(const sigset_t *sigmask);

調(diào)用sigsuspend時,進(jìn)程的信號屏蔽字由sigmask參數(shù)指定,可以通過指定sigmask來臨時解除對某個信號的屏蔽,然后掛起等待,當(dāng)sigsuspend返回時,進(jìn)程的信號屏蔽字恢復(fù)為原來的值,如果原來對該信號是屏蔽的,從sigsuspend返回后仍然是屏蔽的。

實現(xiàn)代碼如下:

#include<stdio.h> #include<signal.h>void myhandler(int sig) {}unsigned int mysleep(unsigned int timeout) {struct sigaction act,oact;sigset_t newmask,oldmask,suspmask;act.sa_handler = myhandler;sigemptyset(&act.sa_mask);act.sa_flags = 0;sigemptyset(&newmask);sigaddset(&newmask,SIGALRM);sigprocmask(SIG_BLOCK,&newmask,&oldmask);sigaction(SIGALRM,&act,&oact); //信號注冊函數(shù)alarm(timeout); //鬧鐘timeout秒后響suspmask = oldmask;sigdelset(&suspmask,SIGALRM);sigsuspend(&suspmask);//pause(); //掛起等待unsigned int ret = alarm(0); //清空鬧鐘sigaction(SIGALRM,&oact,NULL);sigprocmask(SIG_SETMASK,&oldmask,NULL);return ret; }int main() {printf("ready sleeping!\n");mysleep(3);printf("i am waking!\n");return 0; }

運行結(jié)果:

3秒之后:

總結(jié)

以上是生活随笔為你收集整理的[Linux]继续探究mysleep函数(竞态条件)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。