12.8 線程和信號


在基于進程模型的信號處理已經比較嗎麻煩了,引入線程后事情就更加復雜了。
每個線程擁有其自身的信號掩碼,但是信號處理函數是被進程內的所有線程共享的,作為一個推論,獨立的線程能夠阻塞信號,但是如果一個線程修改與給定信號的處理動作的時候,所有的線程都會共享這一修改。也就是說,如果一個線程選擇忽略一個給定信號,其他的線程可能會通過恢復默認呢處理或者是安裝信號處理函數的方式撤銷線程所做的忽略選擇。
信號會只會被發送到進程內的一個線程。如果信號與硬件錯誤相關,那么信號通常被發送到造成時間發生的線程,其他信號,將被發送到任意一個線程。
在10.12節中,我們介紹了進程可以使用函數sigprocmask函數來阻塞信號的發送,然而,sigprocmask函數在多線程進程中的行為是未定義的,線程必須使用函數pthread_sigmask予以代替。

  1. #include <signal.h>
  2. int pthread_sigmask(int how, const sigset_t *restrict set, sigset_t *restrict oset);
  3. Returns: 0 if OK, error number on failure.

函數pthread_sigmask與函數sigprocmask相似,但是pthread_sigmask函數在失敗的時候返回一個錯誤碼,而函數sigprocmask在失敗的時候返回-1并且設置errno變量。
參數how可以取三個不同的數值:
* SIG_BLOCK添加信號集到線程的信號掩碼中;
* SIG_SETMASK使用信號集替換線程的信號掩碼;
* SIG_UNBLOCK從線程的信號掩碼中移除信號集;
如果oset參數不是null,那么線程的前一個信號掩碼將被存儲到oset指針指向的內存中。線程可以通過設置set參數為null的情況下獲取其當前的信號掩碼,著這種情況下,how參數將被忽略。

線程可以調用函數sigwait來等待一個或者多個信號的出現;

  1. #include <signal.h>
  2. int sigwait(const sigset_t *restrict set, int *restrict signop);
  3. Returns: 0 if OK, error number on failure.

參數set指定了線程正在等待信號的集合,參數signop指針指向的內存將會存儲被發送的信號數量。
如果在sigwait函數被調用的時候,如果set中的一個信號處于掛起狀態,那么函數sigwait就不會阻塞,而是直接返回,在返回之前,sigwait函數將會將從進程掛起的信號集中移除等到的信號。如果實現支持信號排隊,并且一個信號的多個實例處于掛起狀態,函數sigwait僅僅移除其中一個實例,其他實例仍然處于排隊狀態。
為了避免錯誤的行為,線程在調用函數sigwait之前必須先阻塞這些等待的信號。函數sigwait將會自動解除對應信號的阻塞,并且一直等待知道其中一個信號被發送,在返回之前,sigwait將會恢復線程的信號掩碼,如果函數sigwait被調用的時候,對應的信號沒有被阻塞,那么在完成函數sigwait之前會出現一個多于的時間窗口,在這個時間窗口內,信號可能被發送到了線程。
使用函數sigwait的一個好處就是可以簡化信號處理函數的設計,因為它允許我們將異步信號處理當作是同步信號來看待,我們可以通過將指定信號添加到線程的信號掩碼中,從而防止信號中斷線程的執行,然后專門指定一個線程來處理信號,這些指定的線程在調用函數的時候不需要再考慮那些函數是信號處理安全的,因為在信號處理函數被調用的時候,線程處于正常的線程環境,而不是像傳統情況那樣:信號處理函數能夠中斷線程的正常執行。
如果多個線程由于調用了函數sigwait而阻塞在了同一個信號上,那么當信號被發送的時候,僅僅只有一個線程將會返回,如果一個信號被捕獲,并且存在一個線程調用函數sigwait等待這一信號,如何發送信號是交給實現了決定的,實現可以允許sigwait返回或者是調用信號處理函數,但是不能同時執行這兩個動作。
為了發送一個信號給進程,我們可以調用函數kill,為了發送一個信號給一個線程,我們可以調用函數pthread_kill;

  1. #include <signal.h>
  2. int pthread_kill(pthread_t thread, int signl);
  3. Returns: 0 if ok, error number on failure.

我們可以傳遞給參數signo數值0,用于檢測指定線程是否存在。如果一個信號的默認處理方式是終止進程,那么向一個線程發送這個信號也會終止掉整個進程。
注意alarm timers是進程資源,所有的線程都會共享相同的alarms集合,因此,對于一個進程中的多個線程,不可能做到使用alarm timers而不發生沖突。

Example

在圖10.23中,我們等待信號處理函數設置一個標志,用于表示主程序可以退出了。在這個程序中,可以運行的程序流僅僅只有主線程以及信號處理函數,所以阻塞信號對于避免丟失標志的改變是有效的。使用多線程以后,我們需要使用互斥鎖來保護標志,正如在圖12.16中程序所示。

  1. #include "apue.h"
  2. #include <pthread.h>
  3. int quitflag; /* set nonzero by thread */
  4. sigset_t mask;
  5. pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
  6. pthread_cond_t waitloc = PTHREAD_COND_INITIALIZER;
  7. void *thr_fn(void *arg)
  8. {
  9. int err, signo;
  10. for(;;)
  11. {
  12. err = sigwait(&mask, &signo);
  13. if(err != 0)
  14. err_exit(err, "sigwait failed");
  15. switch(signo)
  16. {
  17. case SIGINT:
  18. printf("\ninterrupt\n");
  19. break;
  20. case SIGQUIT:
  21. pthread_mutex_lock(&lock);
  22. quitflag = 1;
  23. pthread_mutex_unlock(&lock);
  24. pthread_cond_signal(&waitloc);
  25. return (0);
  26. default:
  27. printf("unexpected signal %d\n", signo);
  28. exit(1);
  29. }
  30. }
  31. }
  32. int main(void)
  33. {
  34. int err;
  35. sigset_t oldmask;
  36. pthread_t tid;
  37. sigemptyset(&mask);
  38. sigaddset(&mask, SIGINT);
  39. sigaddset(&mask, SIGQUIT);
  40. if((err = pthread_sigmask(SIG_BLOCK, &mask, &oldmask)) != 0)
  41. err_exit(err, "SIG_BLOCK error");
  42. err = pthread_create(&tid, NULL, thr_fn, 0);
  43. if(err != 0)
  44. {
  45. err_exit(err, "can;t create thread");
  46. }
  47. pthread_mutex_lock(&lock);
  48. while(quitflag == 0)
  49. pthread_cond_wait(&waitloc, &lock);
  50. pthread_mutex_unlock(&lock);
  51. /*SIGQIUT has been caught and is now blocked; do whatever */
  52. quitflag = 0;
  53. /*reset signal mask which unblocks ISGQUIT */
  54. if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
  55. err_sys("SIG_SETMASK error");
  56. exit(0);
  57. }

圖12.16 同步信號處理
信號處理函數不再會中斷主線程,我們使用一個專門的線程來處理信號,我們可以在互斥鎖的保護下修改quitflag,so that the main thread of control can’t miss the wake-up call made when we call pthread_cond_signal.我們在主線程中使用同一互斥鎖來檢查標記的值,并在我們等待條件的時候自動釋放鎖。
注意同時阻塞了信號SIGINT以及SIGQUIT信號,當我們創建線程來處理信號的時候,線程繼承了當前的信號掩碼,因為sigwait并不會阻塞信號,因此只有一個線程可以接受信號,這樣可以使得我們在編寫主線程的時候不用考慮這些中斷信號的干擾。
程序運行情況如下入所示:

  1. yuekunhu@debian:~/APUE/chapter12$ ./12_16.exe
  2. ^C
  3. interrupt
  4. ^C
  5. interrupt
  6. ^C
  7. interrupt
  8. ^\yuekunhu@debian:~/APUE/chapter12$



來自為知筆記(Wiz)


轉載于:https://www.cnblogs.com/U201013687/p/5635947.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/395630.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/395630.shtml
英文地址,請注明出處:http://en.pswp.cn/news/395630.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

基于MVC的網站和在線教育系統

最近老表說要創業&#xff0c;想要做一個網站做宣傳&#xff0c;還想要一個在線教育系統。 學習了一部分 Java&#xff0c; 決定用.Net MVC做官網或直接做成靜態HTML網站&#xff0c;主要是因為.Net MVC 技術簡單&#xff0c;效率高&#xff0c;需求不確定。 考慮的點在&#…

密碼學經典之生日悖論與生日攻擊【詳解】

生日悖論 在算法導論書上看到個比較有意思的概率算法&#xff0c;在這里加上自己的理解分享下&#xff1a; 上次剛看同學發的朋友圈說道&#xff1a;“兩個人同一間宿舍&#xff0c;而且同年同月同日生&#xff0c;這個緣分真的是醉了”&#xff0c;當時我也是醉醉的&#xff…

matlab simplify,[求助]Matlab2016b里沒有simple函數

該樓層疑似違規已被系統折疊 隱藏此樓查看此樓function [r,h] simple(s,varargin)%SIMPLE Search for simplest form of a symbolic expression or matrix.% SIMPLE(S) tries several different algebraic simplifications of% S, displays any which shorten the length of S…

網龍面試后多久有回應_回應面試問題

網龍面試后多久有回應For the record, asking someone these questions probably isn’t the best way to get a deep understanding of their experience with React. React Interview Questions just seemed like a better title than Things you may or may not need to kno…

Bagging與隨機森林算法原理小結

在集成學習原理小結中&#xff0c;我們講到了集成學習有兩個流派&#xff0c;一個是boosting派系&#xff0c;它的特點是各個弱學習器之間有依賴關系。另一種是bagging流派&#xff0c;它的特點是各個弱學習器之間沒有依賴關系&#xff0c;可以并行擬合。本文就對集成學習中Bag…

iOS:多線程技術GCD的使用

GCD的使用&#xff1a; 1.隊列的類型1.1 主隊列&#xff1a;mian queue,主線程隊列,負責更行UI的操作。是一個串行的隊列。1.2 系統默認的并行隊列&#xff1a;global queue&#xff0c;按優先級分類。1.3 自定義的隊列&#xff1a;可以創建串行隊列或者是并行的隊列2.任務2.1 …

java什么叫一致性,java-順序一致性易失性說明

我正在從Java Jpoint會議觀看視頻.我對以下來自Alexey Shipilev報告的幻燈片有疑問&#xff1a;打擾一下,請不要打擾我.實際上,作者說不可能將變量集設置為r1 1 (Y)r2 0 (x)r3 1 (x)r4 0 (Y)根據視頻,他暗示很明顯.有人可以澄清為什么JMM無法設置此值嗎&#xff1f;附言如果…

模塊制作標準說明

原則一&#xff1a;CSS定義越少越好原則二&#xff1a;進來用<ul><li>等簡單的HTML代碼結構原則三&#xff1a;命名盡可能用CSS偽類原則四&#xff1a;一個模塊CSS名稱不能超過三個需要改正的寫法&#xff1a; <div class"fenglei"><div class&…

【c++】string類的使用

目錄 一、標準庫中的string類 1、簡單介紹string類 2、string類的常用接口注意事項 2.1、string類對象的常用構造 2.2、string類對象的容量操作 2.3、string類對象的訪問及遍歷操作 2.4、string類對象的修改操作 二、string類的模擬實現 一、標準庫中的string類 1、簡…

拜托了

by Buddy Reno由Buddy Reno Git Please &#xff1a;如何在不做蠢事的情況下強行推動 (Git Please: how to force push without being a jerk) As the size of a dev team grows, so does the likelihood of someone doing a force push and overwriting someone else’s code…

性能測試類型

1.驗收性能測試 驗收性能測試&#xff08;Acceptance Performance Testing&#xff09;方法通過模擬生產運行的業務壓力量和使用場景組合&#xff0c;測試系統的性能是否滿足生產性的要求。通俗的說&#xff1a;在特定的運行條件下驗證系統的能力狀況。 &#xff08;1&#xff…

Java - 對象(object) 具體解釋

對象(object) 具體解釋 本文地址: http://blog.csdn.net/caroline_wendy/article/details/24059545 對象(object)的實例能夠是 物理對象(如 人, 車等實物) 或 邏輯對象(如 運動, 健康等); 對象是將狀態(數據) 和行為(功能) 組合在一起的軟件模塊. 類是描寫敘述一組相似對象共同…

kkt條件的matlab仿真,請教關于SVM中KKT條件的推導

KKT條件第一項是說最優點必須滿足所有等式及不等式限制條件&#xff0c;也就是說最優點必須是一個可行解&#xff0c;這一點自然是毋庸置疑的。第二項表明在最優點 x*&#xff0c; ?f 必須是 ?hj 和 ?gk 的線性組合&#xff0c;和都叫作拉格朗日乘子。所不同的是不等式限制條…

公共wifi做家用_如何在公共網絡上獲得免費的wifi

公共wifi做家用by Kyle McDonald凱爾麥克唐納(Kyle McDonald) 如何在公共網絡上獲得免費的wifi (How to get free wifi on public networks) This short tutorial describes a few methods for gaining access to the internet, a basic human right, from public wireless ne…

python學習之旅

一、入門 1.Python 面向對象編程 2.jquery入門 3.HTMLCSS基礎入門 4.Javascript初步 5.Python語言編程基礎 二、初級階段 1.Git 與 GitHub 2.Python 爬蟲基礎 3.django進階 4.django項目部署 5.ajax入門 6.django基礎 7.Mysql基礎 三、中級階段 1.Linux基礎 2.Python :socket a…

c/c++ 重載運算符 函數調用運算符

重載運算符 函數調用運算符 把一個類的對象a&#xff0c;當成函數來使用&#xff0c;比如a()&#xff0c;所以需要重載operator()方法。重載了函數調用運算符的類的對象&#xff0c;就是函數對象了。 還有什么是函數對象呢&#xff1f;&#xff1f;&#xff1f; lambda是函數對…

matlab 萬能,matlab 萬能實用的線性曲線擬合方法

在科學計算和工程應用中&#xff0c;經常會遇到需要擬合一系列的離散數據&#xff0c;最近找了很多相關的文章方法&#xff0c;在這里進行總結一下其中最完整、幾乎能解決所有離散參數線性擬合的方法第一步&#xff1a;得到散點數據根據你的實際問題得到一系列的散點例如&#…

socket websocket

1.websocket客戶端 websocket允許通過JavaScript建立與遠程服務器的連接&#xff0c;從而實現客戶端與服務器間雙向的通信。在websocket中有兩個方法&#xff1a;      1、send() 向遠程服務器發送數據    2、close() 關閉該websocket鏈接  websocket同時還定義了幾…

javascript原型_JavaScript的原型:古怪,但這是它的工作原理

javascript原型by Pranav Jindal通過普拉納夫金達爾 JavaScript的原型&#xff1a;古怪&#xff0c;但這是它的工作原理 (Prototype in JavaScript: it’s quirky, but here’s how it works) The following four lines are enough to confuse most JavaScript developers:以下…

mysql函數之SUBSTRING_INDEX(str,/,-1)

SUBSTRING_INDEX的用法&#xff1a; ?SUBSTRING_INDEX(str,delim,count) 在定界符 delim 以及count 出現前&#xff0c;從字符串str返回自字符串。若count為正值,則返回最終定界符(從左邊開始) 若為-1則是從后往前截取 SELECT substring_index(Hn_P00001, P, -1) -- 結果是…