国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 操作系統(tǒng) > 正文

線程控制之線程和信號(hào)

2024-06-28 13:28:10
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友
線程控制之線程和信號(hào)

每個(gè)線程都有自己的信號(hào)屏蔽字,但是信號(hào)的處理是進(jìn)程中所有線程共享的。這意味著盡管單個(gè)線程可以阻止某些信號(hào),但當(dāng)線程修改了與某個(gè)信號(hào)相關(guān)的處理行為以后,所有的線程都必須共享這個(gè)處理行為的改變。

進(jìn)程中的信號(hào)是遞送到單個(gè)線程的。如果信號(hào)與硬件故障或計(jì)時(shí)器超時(shí)相關(guān),該信號(hào)就被發(fā)送到引起該事件的線程中去,而其他的信號(hào)則被發(fā)送到任意一個(gè)線程。

http://www.CUOXin.com/nufangrensheng/p/3515257.html中討論了進(jìn)程如何使用sigPRocmask來(lái)阻止信號(hào)發(fā)送。sigpromask的行為在多線程的進(jìn)程中并沒(méi)有定義,線程必須使用pthread_sigmask

#include <signal.h>int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);返回值:若成功則返回0,否則返回錯(cuò)誤編號(hào)

pthread_sigmask函數(shù)與sigprocmask函數(shù)基本相同,除了pthread_sigmask工作在線程中,并且失敗時(shí)返回錯(cuò)誤碼,而不像sigprocmask中那樣設(shè)置errno并返回-1。

線程可以通過(guò)調(diào)用sigwait等待一個(gè)或多個(gè)信號(hào)發(fā)生。

#include <signal.h>int sigwait(const sigset_t *restrict set, int *restrict signop);返回值:若成功則返回0,否則返回錯(cuò)誤編號(hào)

set參數(shù)指出了線程等待的信號(hào)集,signop指向的整數(shù)將作為返回值,表明信號(hào)編號(hào)。

如果信號(hào)集中的某個(gè)信號(hào)在sigwait調(diào)用的時(shí)候處于未決狀態(tài),那么sigwait將無(wú)阻塞地返回,在返回之前,sigwait將從進(jìn)程中移除那些處于未決狀態(tài)的信號(hào)。為了避免錯(cuò)誤動(dòng)作發(fā)生,線程在調(diào)用sigwait之前,必須阻塞那些它正在等待的信號(hào)。sigwait函數(shù)會(huì)自動(dòng)取消信號(hào)集的阻塞狀態(tài),直到有新的信號(hào)被遞送。在返回之前,sigwait將恢復(fù)線程的信號(hào)屏蔽字。如果信號(hào)在sigwait調(diào)用的時(shí)候沒(méi)有被阻塞,在完成對(duì)sigwait調(diào)用之前會(huì)出現(xiàn)一個(gè)時(shí)間窗,在這個(gè)時(shí)間窗口期,某個(gè)信號(hào)可能在完成sigwait調(diào)用之前就被遞送了。

使用sigwait的好處在于它可以簡(jiǎn)化信號(hào)處理,允許把異步產(chǎn)生的信號(hào)用同步的方式處理。為了防止信號(hào)中斷線程,可以把信號(hào)加到每個(gè)線程的信號(hào)屏蔽字中,然后安排專用線程作信號(hào)處理。這些專用線程可以進(jìn)行函數(shù)調(diào)用,不需要擔(dān)心在信號(hào)處理程序中調(diào)用哪些函數(shù)是安全的,因?yàn)檫@些函數(shù)調(diào)用來(lái)自正常的線程環(huán)境,而非傳統(tǒng)的信號(hào)處理程序,傳統(tǒng)信號(hào)處理程序通常會(huì)中斷線程的正常執(zhí)行。

如果多個(gè)線程在sigwait調(diào)用時(shí),等待的是同一個(gè)信號(hào),這時(shí)就會(huì)出現(xiàn)線程阻塞。當(dāng)信號(hào)遞送的時(shí)候,只有一個(gè)線程可以從sigwait中返回。如果信號(hào)被捕獲(例如進(jìn)程通過(guò)使用sigaction建立了一個(gè)信號(hào)處理函數(shù)),而且線程正在sigwait調(diào)用中等待同一個(gè)信號(hào),那么這時(shí)將由操作系統(tǒng)實(shí)現(xiàn)來(lái)決定以何種方式遞送信號(hào)。在這種情況下,操作系統(tǒng)實(shí)現(xiàn)可以讓sigwait返回,也可以激活信號(hào)處理程序,但不可能出現(xiàn)兩者皆可的情況。

要把信號(hào)發(fā)送到進(jìn)程,可以調(diào)用kill(見(jiàn)http://www.CUOXin.com/nufangrensheng/p/3514817.html);要把信號(hào)發(fā)送到線程,可以調(diào)用pthread_kill。

#include <signal.h>int pthread_kill(pthread_t thread, int signo);返回值:若成功則返回0,否則返回錯(cuò)誤編號(hào)

可以傳一個(gè)0值的signo來(lái)檢查線程是否存在。如果信號(hào)的默認(rèn)處理動(dòng)作是終止該進(jìn)程,那么把信號(hào)傳遞給某個(gè)線程仍然會(huì)殺掉整個(gè)進(jìn)程。

注意鬧鐘定時(shí)器是進(jìn)程資源,并且所有的線程共享相同的alarm。所以進(jìn)程中的多個(gè)線程不可能互不干擾(或互不合作)地使用鬧鐘定時(shí)器。

實(shí)例

回憶程序清單10-16(http://www.CUOXin.com/nufangrensheng/p/3516427.html),等待信號(hào)處理程序設(shè)置標(biāo)志,從而表明主程序應(yīng)該退出。唯一可運(yùn)行的控制線程就是主線程和信號(hào)處理程序,所以阻塞信號(hào)足以避免錯(cuò)失標(biāo)志修改。在線程中,需要使用互斥量來(lái)保護(hù)標(biāo)志,如程序清單12-6所示。

程序清單12-6 同步信號(hào)處理

#include "apue.h"#include <pthread.h>int        quitflag;    /* set nonzero by thread */sigset_t    mask;pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;pthread_cond_t    wait = PTHREAD_COND_INITIALIZER;void *thr_fn(void *arg){    int err, signo;        for(; ;)    {        err = sigwait(&mask, &signo);        if(err != 0)            err_exit(err, "sigwait failed");        switch(signo)        {            case SIGINT:                printf("/ninterrupt/n");                break;                    case SIGQUIT:                pthread_mutex_lock(&lock);                quitflag = 1;                pthread_mutex_unlock(&lock);                pthread_cond_signal(&wait);                return(0);            default:                printf("unexpected signal %d/n", signo);                exit(1);                }    }}int main(void){    int        err;    sigset_t    oldmask;    pthread_t    tid;    sigemptyset(&mask);    sigaddset(&mask, SIGINT);    sigaddset(&mask, SIGQUIT);        if((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0)        err_exit(err, "SIG_BLOCK error");        err = pthread_create(&tid, NULL, thr_fn, 0);    if(err != 0)        err_exit(err, "can't create thread");    pthread_mutex_lock(&lock);    while(quitflag == 0)        pthread_cond_wait(&wait, &lock);    pthread_mutex_unlock(&lock);    /* 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);}

這里并不讓信號(hào)處理程序中斷主控線程,而是由專門的獨(dú)立控制線程進(jìn)行信號(hào)處理。改動(dòng)quitflag的值是在互斥量的保護(hù)下進(jìn)行的,這樣主控線程不會(huì)在調(diào)用pthread_cond_signal時(shí)錯(cuò)失喚醒調(diào)用。在主控線程中使用相同的互斥量來(lái)檢查標(biāo)志的值,并且原子地釋放互斥量,等待條件的發(fā)生。

注意在主線程開始時(shí)阻塞SIGINT和SIGQUIT。當(dāng)創(chuàng)建線程進(jìn)行信號(hào)處理時(shí),新建線程繼承了現(xiàn)有的信號(hào)屏蔽字。因?yàn)閟igwait會(huì)解除信號(hào)的阻塞狀態(tài),所以只有一個(gè)線程可以用于信號(hào)的接收。這使得對(duì)主線程進(jìn)行編碼時(shí)不必?fù)?dān)心來(lái)自這些信號(hào)的中斷。

運(yùn)行這個(gè)程序可以得到與程序10-16類似的輸出結(jié)果:

interrupt        鍵入中斷字符interrupt        再次鍵入中斷字符interrupt        再一次                    用結(jié)束字符終止

本篇博文內(nèi)容摘自《UNIX環(huán)境高級(jí)編程》(第二版),僅作個(gè)人學(xué)習(xí)記錄所用。關(guān)于本書可參考:http://www.apuebook.com/


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 宁化县| 平陆县| 江川县| 旌德县| 翁源县| 台南县| 长兴县| 仪征市| 成武县| 游戏| 梓潼县| 庄河市| 开化县| 太康县| 凤翔县| 忻州市| 闸北区| 乌兰浩特市| 称多县| 子长县| 于都县| 灯塔市| 白河县| 原平市| 奉贤区| 雷州市| 大埔县| 宜宾市| 喀喇沁旗| 巴林右旗| 南阳市| 贺兰县| 读书| 丰县| 石家庄市| 泰兴市| 和平区| 平果县| 扎鲁特旗| 社旗县| 昭苏县|