亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 操作系統 > 正文

信號之sigsuspend函數

2024-06-28 13:28:26
字體:
來源:轉載
供稿:網友
信號之sigsuspend函數

更改進程的信號屏蔽字可以阻塞所選擇的信號,或解除對它們的阻塞。使用這種技術可以保護不希望由信號中斷的代碼臨界區。如果希望對一個信號解除阻塞,然后pause等待以前被阻塞的信號發生,則又將如何呢?假定信號時SIGINT,實現這一點的一種不正確的方法是:

sigset_t    newmask, oldmask;sigemptyset(&newmask);sigaddset(&newmask, SIGINT);/* block SIGINT and save current signal mask */if(sigPRocmask(SIG_BLOCK, &newmask, &oldmask) < 0)    err_sys("SIG_BLOCK error");/* critical region of code */if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)    err_sys("SIG_SETMASK error");/* window is open */pause();    /* wait for signal to occur *//* continue processing */

如果在信號阻塞時將其發送給進程,那么該信號的傳遞就被推遲直到對它解除了阻塞。對應用程序而言,該信號好像發生在解除對SIGINT的阻塞和pause之間。如果發生了這種情況,或者如果在解除阻塞時刻和pause之間確實發生了信號,那么就產生了問題。因為我們可能不會再見到該信號,所以從這種意義上而言,在此時間窗口(解除阻塞和pause之間)中發生的信號丟失了,這樣就使pause永遠阻塞。

為了糾正此問題,需要在一個原子操作中先恢復信號屏蔽字,然后使進程休眠。這種功能是由sigsuspend函數提供的。

#include <signal.h>int sigsuspend( const sigset_t *sigmask );返回值:-1,并將errno設置為EINTR

未命名

將進程的信號屏蔽字設置為由sigmask指向的值。在捕捉到一個信號或發生了一個會終止該進程的信號之前,該進程被掛起。如果捕捉到一個信號而且從該信號處理程序返回,則sigsuspend返回,并且將該進程的信號屏蔽字設置為調用sigsuspend之前的值。

注意,此函數沒有成功返回值。如果它返回到調用者,則總是返回-1,并將errno設置為EINTR(表示一個被中斷的系統調用)。

實例

程序清單10-15顯示了保護臨界區,使其不被特定信號中斷的正確方法。

程序清單10-15 保護臨界區不被信號中斷

#include "apue.h"static void sig_int(int);intmain(void){    sigset_t     newmask, oldmask, waitmask;        pr_mask("program start: ");    if(signal(SIGINT, sig_int) == SIG_ERR)        err_sys("signal(SIGINT) error");    sigemptyset(&waitmask);    sigaddset(&waitmask, SIGUSR1);    sigemptyset(&newmask);    sigaddset(&newmask, SIGINT);    /*    * Block SIGINT and save current signal mask.    */    if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)        err_sys("SIG_BLOCK error: ");    /*    * Critical region of code.    */    pr_mask("in critical region: ");    /*    * Pause, allowing all signals except SIGUSR1.    */    if(sigsuspend(&waitmask) != -1)        err_sys("sigsuspend error");        pr_mask("after return from sigsuspend: ");    /*    * Reset signal mask which unblocks SIGINT.    */    if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)        err_sys("SIG_SETMASK error");    /*    * And continue processing...    */    pr_mask("program exit: ");    exit(0);}static voidsig_int(int signo){    pr_mask("/nin sig_int: ");}

運行該程序的結果如下:

未命名

此結果與《UNIX環境高級編程》中的結果不一致,不同之處在于,in sig_int:SIGINT SIGUSR1。(在處理某一信號的時候會不會把該信號暫時阻塞直到對該信號的信號處理函數返回。)這里的問題與http://www.CUOXin.com/nufangrensheng/p/3516134.html中最后的問題其實是一個性質的問題。我想可能是由于實現版本不同造成的吧。

 

實例

sigsuspend的另一種應用是等待一個信號處理程序設置一個全局變量。程序清單10-16用于捕捉中斷信號和退出信號,但是希望僅當捕捉到退出信號時,才喚醒主例程。

程序清單10-16 用sigsuspend等待一個全局變量被設置

#include "apue.h"volatile sig_atomic_t    quitflag;    /* set nonzero by signal handler */static voidsig_int(int signo)    /* one signal handler for SIGINT and SIGQUIT */{    signal(SIGINT, sig_int);    signal(SIGQUIT, sig_int);    if (signo == SIGINT)        printf("/ninterrupt/n");    else if (signo == SIGQUIT)        quitflag = 1;    /* set flag for main loop */}intmain(void){    sigset_t    newmask, oldmask, zeromask;    if(signal(SIGINT, sig_int) == SIG_ERR)        err_sys("signal(SIGINT) error");    if(signal(SIGQUIT, sig_int) == SIG_ERR)        err_sys("signal(SIGQUIT) error");    sigemptyset(&zeromask);    sigemptyset(&newmask);    sigaddset(&newmask, SIGQUIT);    /*    * Block SIGQUIT and save current signal mask.    */    if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)        err_sys("SIG_BLOCK error");    while(quitflag == 0)    {        sigsuspend(&zeromask);    }    /*    * SIGQUIT has been caught and is now blocked; do whatever.    */    quitflag = 0;    /*    * Reset signal mask which unblocks SIGQUIT.    */    if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)        err_sys("SIG_SETMASK error");        exit(0);}

注意,程序清單10-16中標記為紅色字體的兩行在《UNIX環境高級編程》中本來是沒有的,但是不加這兩行,在我的運行環境下(Red Hat linux 2.6.18)得不到跟書中一樣的運行結果:

書中的運行結果(可以反復鍵入中斷字符):

未命名

我的運行結果(鍵入一次中斷字符后,第二次鍵入中斷字符就退出了):

未命名

而在程序中加入上面帶紅色標記的語句后,則可以得到與書中同樣的結果。

出現上面現象的原因是:對于書中的UNIX版本:一旦對給定的信號設置了一個動作,那么在調用sigaction(signal函數的實現其實就是調用sigaction)顯式地改變它之前,該設置就一直有效。而對于我的版本:在進程每次接到信號對其進行處理時,隨即將該信號動作復位為默認值(早期版本)。詳情可參考:http://www.CUOXin.com/nufangrensheng/p/3515945.html

 

實例

可以用信號實現父、子進程之間的同步,這是信號應用的另一個實例。程序清單10-17包含了http://www.CUOXin.com/nufangrensheng/p/3510306.html中提到的五個例程的實現,它們是:TELL_WAIT、TELL_PARENT、TELL_CHILD、WAIT_PARENT和WAIT_CHILD。

程序清單10-17 父子進程可用來實現同步的例程

#include "apue.h"static volatile sig_atomic_t sigflag;    /* set nonzero by sig handler */static sigset_t    newmask, oldmask, zeromask;static voidsig_usr(int signo)    /* one signal handler for SIGUSR1 and SIGUSR2 */{    sigflag = 1;}voidTELL_WAIT(void){    if (signal(SIGUSR1, sig_usr) == SIG_ERR)        err_sys("signal(SIGUSR1) error");    if (signal(SIGUSR2, sig_usr) == SIG_ERR)        err_sys("signal(SIGUSR2) error");    sigemptyset(&zeromask);    sigemptyset(&newmask);    sigaddset(&newmask, SIGUSR1);    sigaddset(&newmask, SIGUSR2);    /*    * Block SIGUSR1 and SIGUSR2, and save current signal mask.    */    if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)        err_sys("SIG_BLOCK error");}voidTELL_PARENT(pid_t pid){    kill(pid, SIGUSR2);    /* tell parent we're done */}voidWAIT_PARENT(void){    while(sigflag == 0)            sigsuspend(&zeromask);    /* and wait for parent */    sigflag = 0;    /*    * Reset signal mask to original value.    */    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)        err_sys("SIG_SETMASK error");}void TELL_CHILD(pid_t pid){    kill(pid, SIGUSR1);}voidWAIT_CHILD(void){    while(sigflag == 0)        sigsuspend(&zeromask);    /* and wait for child */    sigflag = 0;    /*    * Reset signal mask to original value.     */    if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)        err_sys("SIG_SETMASK error");}

其中使用了兩個用戶定義的信號:SIGUSR1由父進程發送給子進程,SIGUSR2由子進程發送給父進程。

如果在等待信號發生時希望去休眠,則使用sigsuspend函數是非常合適的,但是如果在等待信號期間希望調用其他系統函數,那么將會怎樣呢?不幸的是,在單線程環境下對此問題沒有妥善的解決方法。如果可以使用多線程,則可專門安排一個線程處理信號。

如果不使用線程,那么我們能盡力做到最好的是,當信號發生時,在信號捕捉程序中對一個全局變量置1.

 

本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精品国亚洲| 国产精品久久久久免费a∨大胸| 欧美激情第三页| 欧美性受xxx| 欧美专区中文字幕| 欧美男插女视频| 国产午夜精品全部视频在线播放| 日韩av手机在线观看| 伊人久久久久久久久久久| www.亚洲免费视频| 国产精品国产福利国产秒拍| 一区二区三区四区在线观看视频| 国产精品视频中文字幕91| 久热精品视频在线观看| 国产午夜精品全部视频在线播放| 一道本无吗dⅴd在线播放一区| 成人在线免费观看视视频| 日本电影亚洲天堂| 亚洲aaaaaa| 日韩毛片在线观看| 国产精品欧美日韩久久| 亚洲欧美精品中文字幕在线| 欧美黑人xxxx| 精品久久香蕉国产线看观看亚洲| 亚洲jizzjizz日本少妇| 在线观看国产欧美| 日韩精品高清视频| 国产精品男女猛烈高潮激情| 久久国产精品网站| 日韩综合视频在线观看| 欧美一级在线亚洲天堂| www.久久草.com| 激情成人在线视频| 日韩欧美成人免费视频| 午夜精品蜜臀一区二区三区免费| 国产午夜精品免费一区二区三区| 久久久久国产视频| 日韩精品在线播放| 久久久国产视频91| 亚洲国产精品美女| 韩国国内大量揄拍精品视频| 亚洲福利在线视频| 97精品在线观看| 国产精品一二三视频| 伊人久久久久久久久久| 欧美在线一级va免费观看| 欧美性色xo影院| 亚洲精品国产精品乱码不99按摩| 国产一区二区三区欧美| 欧美日韩aaaa| 亚洲第一福利网| 在线电影欧美日韩一区二区私密| 欧美激情第99页| 国产精品白嫩初高中害羞小美女| 亚洲人成绝费网站色www| 亚洲国产成人久久| 7777免费精品视频| 亚洲国产精品va在看黑人| 88国产精品欧美一区二区三区| 精品在线欧美视频| 久久韩国免费视频| 亚洲最新av在线网站| 欧美影院成年免费版| 欧美国产亚洲视频| 欧美日韩在线观看视频小说| 日韩中文在线观看| 国产精品精品一区二区三区午夜版| 亚洲人成在线免费观看| 国产精品久久97| 国产一区二区欧美日韩| 欧美一级电影久久| 亚洲专区在线视频| 91欧美精品午夜性色福利在线| 欧美激情三级免费| 久久久国产一区二区| 日韩精品在线视频| 午夜精品一区二区三区视频免费看| 亚洲曰本av电影| 国产网站欧美日韩免费精品在线观看| 久久影院资源网| 久久精品一本久久99精品| 日韩一区二区三区xxxx| 中文字幕成人在线| 国产欧美欧洲在线观看| 色悠悠久久久久| 亚洲一区二区三区乱码aⅴ蜜桃女| 欧美中文字幕第一页| 亚洲免费一级电影| 国产精品女主播视频| 日韩av免费在线| 在线视频国产日韩| 欧美一级在线播放| 欧美日本亚洲视频| 97精品国产97久久久久久春色| 国产香蕉一区二区三区在线视频| 欧美高清视频免费观看| 亚洲午夜久久久影院| 欧美猛交ⅹxxx乱大交视频| 91在线观看欧美日韩| 国产精品老女人精品视频| 国产精品久久久久秋霞鲁丝| 国产精品久久久久久久午夜| 2019国产精品自在线拍国产不卡| 亚洲人成在线播放| 社区色欧美激情 | 欧美精品18videos性欧美| 中文字幕亚洲综合久久| 亚洲伦理中文字幕| 日韩在线播放一区| 91啪国产在线| 亚洲成人国产精品| 日韩av在线播放资源| 欧美日韩第一视频| 中文字幕亚洲图片| 18性欧美xxxⅹ性满足| 久久久亚洲国产天美传媒修理工| 日韩精品在线第一页| 日韩精品在线免费观看视频| 欧美大片免费观看在线观看网站推荐| 精品调教chinesegay| 亚洲精品电影网站| 国产91露脸中文字幕在线| 亚洲欧美精品伊人久久| 久久久久国产精品免费| 91久久精品国产91久久性色| 国产精品福利久久久| 欧美激情视频在线| 欧美激情国产精品| 日韩在线观看高清| 亚洲图片在区色| 国产欧美在线看| 国产精品成av人在线视午夜片| 久久精品国产亚洲一区二区| 国产成人精品亚洲精品| 亚洲激情在线视频| 日韩av影视综合网| 92看片淫黄大片看国产片| 久久精视频免费在线久久完整在线看| 久久九九亚洲综合| 欧美—级高清免费播放| 成人免费直播live| 亚洲欧洲成视频免费观看| 久久伊人免费视频| 97香蕉久久夜色精品国产| 一区二区三区天堂av| 欧美性猛交丰臀xxxxx网站| 欧美成人精品激情在线观看| 欧美激情免费看| 91精品视频在线| 国产精品国内视频| 久久成人av网站| 北条麻妃久久精品| 成人亚洲欧美一区二区三区| 亚洲偷熟乱区亚洲香蕉av| 一级做a爰片久久毛片美女图片| 亚洲最大福利视频| 超薄丝袜一区二区| 欧美激情精品久久久久久大尺度| 日韩av免费看网站| 国产精品爱啪在线线免费观看| 国内揄拍国内精品| 高清欧美电影在线| 韩国三级电影久久久久久| 68精品国产免费久久久久久婷婷|