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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux系统编程----8(竞态条件,时序竞态,pause函数,如何解决时序竞态)

發(fā)布時間:2023/11/30 linux 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程----8(竞态条件,时序竞态,pause函数,如何解决时序竞态) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

競態(tài)條件(時序競態(tài)):

pause 函數(shù)

調(diào)用該函數(shù)可以造成進(jìn)程主動掛起,等待信號喚醒。調(diào)用該系統(tǒng)調(diào)用的進(jìn)程將處于阻塞狀態(tài)(主動放棄 cpu) 直 到有信號遞達(dá)將其喚醒,等不到一直等
int pause(void); 返回值:-1 并設(shè)置 errno 為 EINTR

返回值:
  • 如果信號的默認(rèn)處理動作是終止進(jìn)程,則進(jìn)程終止,pause 函數(shù)么有機(jī)會返回。
  • 如果信號的默認(rèn)處理動作是忽略,進(jìn)程繼續(xù)處于掛起狀態(tài),pause 函數(shù)不返回。
  • 如果信號的處理動作是捕捉,則【調(diào)用完信號處理函數(shù)之后,pause 返回-1】 errno 設(shè)置為 EINTR,表示“被信號中斷”。想想我們還有哪個函數(shù)只有出錯返回值。
  • pause 收到的信號不能被屏蔽如果被屏蔽,那么 pause 就不能被喚醒。
  • 使用 pause 和 alarm 來實(shí)現(xiàn) sleep 函數(shù)。
    /** 模擬實(shí)現(xiàn)sleep*/ #include<stdio.h> #include<unistd.h> #include<stdlib.h> #include<signal.h> #include<errno.h> void catch_sigalrm(int signo)//捕捉函數(shù) 保證pause不會被殺死 {; }unsigned int mysleep(unsigned int seconds) {int ret;struct sigaction act,oldact;act.sa_handler = catch_sigalrm;sigemptyset(&act.sa_mask);act.sa_flags = 0;ret = sigaction(SIGALRM,&act,&oldact);//注冊捕捉函數(shù) 改變了SIGALRM信號的設(shè)置if(ret == -1){perror("sigaction error");exit(1);} alarm(seconds); ret = pause();//主動掛起 等信號if(ret == -1 && errno == EINTR){printf("pause sucess\n");} alarm(0);//將鬧鐘清零sigaction(SIGALRM,&oldact,NULL);//恢復(fù)SIGALRN信號舊有的處理方式return ret; } int main(void) {while(1){mysleep(3);printf("-----------------\n");}return 0; }

    時序競態(tài)

    欲睡覺,定鬧鐘 10 分鐘,希望 10 分鐘后鬧鈴將自己喚醒。 正常:定時,睡覺,10 分鐘后被鬧鐘喚醒。
    異常:鬧鐘定好后,被喚走,外出勞動,20 分鐘后勞動結(jié)束。回來繼續(xù)睡覺計劃,但勞動期間鬧鐘已經(jīng)響過, 不會再將我喚醒。

    時序問題分析

    借助 pause 和 alarm 實(shí)現(xiàn)的 mysleep 函數(shù)。設(shè)想如下時序:

  • 注冊 SIGALRM 信號處理函數(shù) (sigaction…) 2
  • 調(diào)用 alarm(1) 函數(shù)設(shè)定鬧鐘 1 秒。
  • 函數(shù)調(diào)用剛結(jié)束,開始倒計時 1 秒。當(dāng)前進(jìn)程失去 cpu,內(nèi)核調(diào)度優(yōu)先級高的進(jìn)程(有多個)取代當(dāng)前進(jìn)程。 當(dāng)前進(jìn)程無法獲得 cpu,進(jìn)入就緒態(tài)等待 cpu。
  • 1 秒后,鬧鐘超時,內(nèi)核向當(dāng)前進(jìn)程發(fā)送 SIGALRM 信號(自然定時法,與進(jìn)程狀態(tài)無關(guān)),高優(yōu)先級進(jìn)程尚未 執(zhí)行完,當(dāng)前進(jìn)程仍處于就緒態(tài),信號無法處理(未決)
  • 優(yōu)先級高的進(jìn)程執(zhí)行完,當(dāng)前進(jìn)程獲得 cpu 資源,內(nèi)核調(diào)度回當(dāng)前進(jìn)程執(zhí)行。SIGALRM 信號遞達(dá),信號設(shè)置 捕捉,執(zhí)行處理函數(shù) sig_alarm。
  • 信號處理函數(shù)執(zhí)行結(jié)束,返回當(dāng)前進(jìn)程主控流程, pause()被調(diào)用掛起等待。 (欲等待alarm函數(shù)發(fā)送的SIGALRM 信號將自己喚醒)
  • SIGALRM 信號已經(jīng)處理完畢,pause 不會等到。
  • 如何解決時序問題(重點(diǎn))

    可以通過設(shè)置屏蔽 SIGALRM 的方法來控制程序執(zhí)行邏輯,但無論如何設(shè)置,程序都有可能在“解除信號屏蔽” 與“掛起等待信號”這個兩個操作間隙失去 cpu 資源。除非將這兩步驟合并成一個“原子操作”。sigsuspend 函數(shù)具 備這個功能。在對時序要求嚴(yán)格的場合下都應(yīng)該使用 sigsuspend 替換 pause。

    int sigsuspend(const sigset_t* mask); 掛起等待信號。
    sigsuspend 函數(shù)調(diào)用期間,進(jìn)程信號屏蔽字由其參數(shù) mask 指定。
    可將某個信號(如 SIGALRM)從臨時信號屏蔽字 mask 中刪除,這樣在調(diào)用 sigsuspend 時將解除對該信號的屏 蔽,然后掛起等待, 當(dāng)sigsuspend返回時,進(jìn)程的信號屏蔽字恢復(fù)為原來的值。 如果原來對該信號是屏蔽態(tài), sigsuspend 函數(shù)返回后仍然屏蔽該信號。

    總結(jié)

  • 競態(tài)條件,跟系統(tǒng)負(fù)載有很緊密的關(guān)系,體現(xiàn)出信號的不可靠性。系統(tǒng)負(fù)載越嚴(yán)重,信號不可靠性越強(qiáng)。
  • 不可靠由其實(shí)現(xiàn)原理所致**。信號是通過軟件方式實(shí)現(xiàn)(跟內(nèi)核調(diào)度高度依賴,延時性強(qiáng)),每次系統(tǒng)調(diào)用結(jié)束后, 或中斷處理處理結(jié)束后,需通過掃描 PCB 中的未決信號集,來判斷是否應(yīng)處理某個信號。**當(dāng)系統(tǒng)負(fù)載過重時,會出 現(xiàn)時序混亂。
  • 這種意外情況只能在編寫程序過程中,提早預(yù)見,主動規(guī)避,而無法通過 gdb 程序調(diào)試等其他手段彌補(bǔ)。且由 于該錯誤不具規(guī)律性,后期捕捉和重現(xiàn)十分困難
  • 總結(jié)

    以上是生活随笔為你收集整理的Linux系统编程----8(竞态条件,时序竞态,pause函数,如何解决时序竞态)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

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