竞态条件
pause函數(shù)
調(diào)用該函數(shù)可以造成進(jìn)程主動(dòng)掛起,等待信號(hào)喚醒。調(diào)用該系統(tǒng)調(diào)用的進(jìn)程將處于阻塞狀態(tài)(主動(dòng)放棄cpu) 直到有信號(hào)遞達(dá)將其喚醒。
????int pause(void); 返回值:-1 并設(shè)置errno為EINTR
返回值:
① 如果信號(hào)的默認(rèn)處理動(dòng)作是終止進(jìn)程,則進(jìn)程終止,pause函數(shù)么有機(jī)會(huì)返回。
② 如果信號(hào)的默認(rèn)處理動(dòng)作是忽略,進(jìn)程繼續(xù)處于掛起狀態(tài),pause函數(shù)不返回。
③ 如果信號(hào)的處理動(dòng)作是捕捉,則【調(diào)用完信號(hào)處理函數(shù)之后,pause返回-1】
? ? ? errno設(shè)置為EINTR,表示“被信號(hào)中斷”。想想我們還有哪個(gè)函數(shù)只有出錯(cuò)返回值。
④ pause收到的信號(hào)不能被屏蔽,如果被屏蔽,那么pause就不能被喚醒。
pause可以和alarm一起實(shí)現(xiàn)sleep函數(shù)功能
#include <stdio.h> #include <unistd.h> #include <stdlib.h> #include <signal.h>void catch_sigalrm(int signo) {; }unsigned int mysleep(unsigned int seconds) {int ret;struct sigaction act, oldact;act.as_handler = catch_sigalrm;sigemptyset(&act.sa_mask); //設(shè)置屏蔽字act.sa_flags = 0;ret = sigaction(SIGALRM, &act, &oldact);if(ret == -1){perror("sigaction error");exit(1);}alarm(seconds);ret = pause(); //主動(dòng)掛起 等信號(hào)if(ret == -1 && errno == EINTR){printf("pause sucess");}ret = alarm(0); //重置alarmsigaction(SIGALRM, &oldact, NULL);return ret; }?
時(shí)序競(jìng)態(tài)
設(shè)想如下場(chǎng)景:
欲睡覺(jué),定鬧鐘10分鐘,希望10分鐘后鬧鈴將自己?jiǎn)拘选?/span>
正常:定時(shí),睡覺(jué),10分鐘后被鬧鐘喚醒。
異常:鬧鐘定好后,被喚走,外出勞動(dòng),20分鐘后勞動(dòng)結(jié)束。回來(lái)繼續(xù)睡覺(jué)計(jì)劃,但勞動(dòng)期間鬧鐘已經(jīng)響過(guò),不會(huì)再將我喚醒。
?
?
解決時(shí)序問(wèn)題
?
可以通過(guò)設(shè)置屏蔽SIGALRM的方法來(lái)控制程序執(zhí)行邏輯,但無(wú)論如何設(shè)置,程序都有可能在“解除信號(hào)屏蔽”與“掛起等待信號(hào)”這個(gè)兩個(gè)操作間隙失去cpu資源。除非將這兩步驟合并成一個(gè)“原子操作”。sigsuspend函數(shù)具備這個(gè)功能。在對(duì)時(shí)序要求嚴(yán)格的場(chǎng)合下都應(yīng)該使用sigsuspend替換pause。
?
int sigsuspend(const sigset_t *mask); 掛起等待信號(hào)。
?
sigsuspend函數(shù)調(diào)用期間,進(jìn)程信號(hào)屏蔽字由其參數(shù)mask指定。
?
可將某個(gè)信號(hào)(如SIGALRM)從臨時(shí)信號(hào)屏蔽字mask中刪除,這樣在調(diào)用sigsuspend時(shí)將解除對(duì)該信號(hào)的屏蔽,然后掛起等待,當(dāng)sigsuspend返回時(shí),進(jìn)程的信號(hào)屏蔽字恢復(fù)為原來(lái)的值。如果原來(lái)對(duì)該信號(hào)是屏蔽態(tài),sigsuspend函數(shù)返回后仍然屏蔽該信號(hào)。
修改如下;
?
......//設(shè)置阻塞信號(hào)集,阻塞SIGALRM信號(hào) sigset_t newmask, oldmask, suspmask;sigemptyset(&newmask);sigaddset(&newmask, SIGALRM);sigprocmask(SIG_BLOCK, &newmask, &oldmask); //信號(hào)屏蔽字mask alarm(seconds);//構(gòu)造一個(gè)調(diào)用sigsuspend臨時(shí)有效 阻塞信號(hào)集,在臨時(shí)阻塞信號(hào)集里解除SIGALRM的阻塞suspmask = oldmask;sigdelset(&suspmask, SIGALRM);//sigsuspend調(diào)用期間,采用臨時(shí)阻塞信號(hào)集suspamask替換原有阻塞信號(hào)集,這個(gè)信號(hào)集中不包含SIGALRM信號(hào),同時(shí)掛起等待。當(dāng)sigsuspend被信號(hào)喚醒返回時(shí),恢復(fù)原有的阻塞信號(hào)集sigsuspend(&suspmask);......
?
轉(zhuǎn)載于:https://www.cnblogs.com/lr1402585172/p/10554590.html
總結(jié)