Linux系统编程----8(竞态条件,时序竞态,pause函数,如何解决时序竞态)
競態(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
返回值:
使用 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è)想如下時序:
如何解決時序問題(重點(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é)
總結(jié)
以上是生活随笔為你收集整理的Linux系统编程----8(竞态条件,时序竞态,pause函数,如何解决时序竞态)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 成都大熊猫繁育基地建议游玩时间
- 下一篇: Linux系统编程---8(全局变量异步