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

歡迎訪問 生活随笔!

生活随笔

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

linux

Linux系统编程(五)时序竞态

發(fā)布時(shí)間:2023/11/30 linux 49 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux系统编程(五)时序竞态 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

時(shí)序競(jìng)態(tài)

  • 產(chǎn)生原因
  • 改進(jìn)
  • 總結(jié)

產(chǎn)生原因

#include <cstdio> #include <stdio.h> #include <sys/time.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <errno.h>void catch_sigalrm(int signo) {printf("pause sucess 11111\n"); }unsigned int mysleep(unsigned int seconds) {struct sigaction act, oldact;sigset_t new1,old;act.sa_flags = 0;act.sa_handler = catch_sigalrm;sigemptyset(&act.sa_mask);int ret=sigaction(SIGALRM, &act, &oldact);if (ret == -1){perror("sigaction error:");exit(1);}sigemptyset(&new1);sigemptyset(&old);sigaddset(&new1,SIGALRM);sigaddset(&old, SIGALRM);sigprocmask(SIG_BLOCK,&new1, NULL);sigprocmask(SIG_UNBLOCK, &old, NULL);alarm(seconds);ret=pause();//主動(dòng)掛起 等信號(hào)if (ret == -1 && errno== EINTR){printf("pause sucess \n");}ret=alarm(0);sigaction(SIGALRM,&oldact,NULL);return ret; }int main() {mysleep(3);printf("----------------\n");return 0; }

如果進(jìn)程在執(zhí)行完alarm函數(shù)后,突然失去CPU,被阻塞等待(這是有可能的,進(jìn)程在執(zhí)行過程中,若非原子操作,都有可能隨時(shí)失去CPU),如果失去CPU的時(shí)間大于了執(zhí)行完,則此時(shí)在執(zhí)行pause函數(shù)前,信號(hào)已經(jīng)到了,因此會(huì)先處理信號(hào)(軟中斷,而不是先執(zhí)行pause函數(shù)),在信號(hào)處理完后,再去執(zhí)行pause函數(shù),此時(shí)進(jìn)程會(huì)被永遠(yuǎn)掛起,不會(huì)被喚醒,因?yàn)镾IGALRM信號(hào)已經(jīng)被處理了。
時(shí)序競(jìng)態(tài):即由于進(jìn)程之間執(zhí)行的順序不同,導(dǎo)致同一個(gè)進(jìn)程多次運(yùn)行后產(chǎn)生了不同結(jié)果的現(xiàn)象。如上述sleep函數(shù),有時(shí)執(zhí)行結(jié)果是正確的,有時(shí)卻會(huì)導(dǎo)致進(jìn)程永遠(yuǎn)被掛起,因此這就是一個(gè)時(shí)序競(jìng)態(tài)問題。因此需要重新對(duì)該函數(shù)進(jìn)行改進(jìn)。

改進(jìn)

代碼如下(示例):

#include <cstdio> #include <stdio.h> #include <sys/time.h> #include <unistd.h> #include <signal.h> #include <stdlib.h> #include <errno.h>void doaction(int signo) {printf("---------%d 信號(hào)-------\n",signo); }int mysleep(int second) {int unslept;struct sigaction cur, old;sigset_t n_ew,o_ld,supemask;//安裝信號(hào)cur.sa_flags = 0;sigemptyset(&cur.sa_mask);cur.sa_handler = doaction;sigaction(SIGALRM,&cur, &old);//設(shè)置阻塞信號(hào)集,阻塞SIGALRM信號(hào)sigemptyset(&n_ew);sigaddset(&n_ew,SIGALRM);sigprocmask(SIG_BLOCK,&n_ew, &o_ld);//定時(shí)alarm(second);//構(gòu)建一個(gè)臨時(shí)的sigsuspend有效阻塞信號(hào)集supemask = o_ld;sigemptyset(&supemask);sigsuspend(&supemask);//supemask未阻塞信號(hào)掛起unslept = alarm(0);//恢復(fù)之前狀態(tài)sigaction(SIGALRM,&old,NULL);sigprocmask(SIG_SETMASK,&o_ld,NULL);return unslept;//int ret=pause();//if (ret == -1 && errno == EINTR)//{// printf("pause success\n");//}}int main() {mysleep(3);}

使用sigsuspend函數(shù),sigsuspend具有“原子操作“,這樣就能夠避免。

總結(jié)

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

總結(jié)

以上是生活随笔為你收集整理的Linux系统编程(五)时序竞态的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

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