Linux下多執行緒程式設計與訊號處理易疏忽的一個例子(轉)
Linux下多執行緒程式設計與訊號處理易疏忽的一個例子(轉)[@more@]這幾天把一個網路流量採集器程式基本改好了,原來在main函式中把幾個子執行緒啟動後就睡10分鐘後開始清理子執行緒後退出。現在想改成子執行緒啟動後主執行緒進入無限睡眠,直到收到SIGTERM或SIGINT。主程式如下:
其他標頭檔案
#include//訊號處理所需要的標頭檔案
int main(int argc, char * argv[]){
//其他所需要的變數宣告
sigset_t sig_set,sig_pending;
// 設定訊號阻塞
sigemptyset(&sig_set);
sigaddset(&sig_set,SIGTERM);
sigaddset(&sig_set,SIGINT);
sigprocmask(SIG_BLOCK,&sig_set,NULL);
啟動幾個子執行緒
...........
// 設定訊號阻塞
sigemptyset(&sig_set);
sigaddset(&sig_set,SIGTERM);
sigaddset(&sig_set,SIGINT);
sigprocmask(SIG_BLOCK,&sig_set,NULL);
//主執行緒進入睡眠,等待訊號到達後跳出睡眠
while(1){
sigpending(&sig_pending);
if(sigismember(&sig_pending, SIGTERM)||
sigismember(&sig_pending,SIGINT)){
break;
}
sleep(2);
}
//子執行緒退出情理
................
return 0;
}
程式執行後發現 當按下Ctrl+C後程式沒有出現子執行緒退出時的資訊而是立刻退出,非常奇怪。
仔細分析了一下,發現問題在於忽略了Linux下的多執行緒模型的特點。
Linux下的執行緒實質上是輕量級程式(light weighted process),執行緒生成時會生成對應的程式控制結構,只是該結構與父執行緒的程式控制結構共享了同一個程式記憶體空間。 同時新執行緒的程式控制結構將從父執行緒(程式)處複製得到同樣的程式資訊,如開啟檔案列表和訊號阻塞掩碼等。由於我們是在子執行緒生成之後修改了訊號阻塞掩碼,此刻子執行緒使用的是主執行緒原有的程式資訊,因此子執行緒仍然會對SIGINT和SIGTERM訊號進行反應,因此當我們用Ctrl+C發出了SIGINT訊號的時候,主程式不處理該訊號,而子程式(執行緒)會進行預設處理,即退出。子程式退出的同時會向父程式(執行緒)傳送SIGCHLD訊號,表示子程式退出,由於該訊號沒有被阻塞,因此會導致主程式(執行緒)也立刻退出,出現了前述的執行情況。因而該問題的一個解決方法是在子執行緒生成前進行訊號設定, 或在子執行緒內部進行訊號設定。 由於子執行緒是往往是一個事務處理函式,因此我建議在簡單的情況下采用前者,如果需要處理的訊號比較複雜,那就必須使用後一種方法來處理。這樣,以上的程式邏輯改為如下就可以了:
#include//訊號處理所需要的標頭檔案
int main(int argc, char * argv[]){
//其他所需要的變數宣告
sigset_t sig_set,sig_pending;
啟動幾個子執行緒
...........
//主執行緒進入睡眠,等待訊號到達後跳出睡眠
while(1){
sigpending(&sig_pending);
if(sigismember(&sig_pending, SIGTERM)||
sigismember(&sig_pending,SIGINT)){
break;
}
sleep(2);
}
//子執行緒退出情理
................
return 0;
}
其他標頭檔案
#include
int main(int argc, char * argv[]){
//其他所需要的變數宣告
sigset_t sig_set,sig_pending;
// 設定訊號阻塞
sigemptyset(&sig_set);
sigaddset(&sig_set,SIGTERM);
sigaddset(&sig_set,SIGINT);
sigprocmask(SIG_BLOCK,&sig_set,NULL);
啟動幾個子執行緒
...........
// 設定訊號阻塞
sigemptyset(&sig_set);
sigaddset(&sig_set,SIGTERM);
sigaddset(&sig_set,SIGINT);
sigprocmask(SIG_BLOCK,&sig_set,NULL);
//主執行緒進入睡眠,等待訊號到達後跳出睡眠
while(1){
sigpending(&sig_pending);
if(sigismember(&sig_pending, SIGTERM)||
sigismember(&sig_pending,SIGINT)){
break;
}
sleep(2);
}
//子執行緒退出情理
................
return 0;
}
程式執行後發現 當按下Ctrl+C後程式沒有出現子執行緒退出時的資訊而是立刻退出,非常奇怪。
仔細分析了一下,發現問題在於忽略了Linux下的多執行緒模型的特點。
Linux下的執行緒實質上是輕量級程式(light weighted process),執行緒生成時會生成對應的程式控制結構,只是該結構與父執行緒的程式控制結構共享了同一個程式記憶體空間。 同時新執行緒的程式控制結構將從父執行緒(程式)處複製得到同樣的程式資訊,如開啟檔案列表和訊號阻塞掩碼等。由於我們是在子執行緒生成之後修改了訊號阻塞掩碼,此刻子執行緒使用的是主執行緒原有的程式資訊,因此子執行緒仍然會對SIGINT和SIGTERM訊號進行反應,因此當我們用Ctrl+C發出了SIGINT訊號的時候,主程式不處理該訊號,而子程式(執行緒)會進行預設處理,即退出。子程式退出的同時會向父程式(執行緒)傳送SIGCHLD訊號,表示子程式退出,由於該訊號沒有被阻塞,因此會導致主程式(執行緒)也立刻退出,出現了前述的執行情況。因而該問題的一個解決方法是在子執行緒生成前進行訊號設定, 或在子執行緒內部進行訊號設定。 由於子執行緒是往往是一個事務處理函式,因此我建議在簡單的情況下采用前者,如果需要處理的訊號比較複雜,那就必須使用後一種方法來處理。這樣,以上的程式邏輯改為如下就可以了:
#include
int main(int argc, char * argv[]){
//其他所需要的變數宣告
sigset_t sig_set,sig_pending;
啟動幾個子執行緒
...........
//主執行緒進入睡眠,等待訊號到達後跳出睡眠
while(1){
sigpending(&sig_pending);
if(sigismember(&sig_pending, SIGTERM)||
sigismember(&sig_pending,SIGINT)){
break;
}
sleep(2);
}
//子執行緒退出情理
................
return 0;
}
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/10617731/viewspace-950193/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 一個SystemC執行緒與SystemVerilog執行緒通訊的例子執行緒
- Linux C++ 多執行緒程式設計LinuxC++執行緒程式設計
- Linux系統程式設計之訊號中斷處理(下)Linux程式設計
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- 多執行緒程式設計相關理論執行緒程式設計
- linux 訊號與處理Linux
- Linux多執行緒伺服器端程式設計Linux執行緒伺服器程式設計
- 多執行緒程式設計總結:一、認識多執行緒本質執行緒程式設計
- Android 資料庫綜述(二) 程式計算器與訊號量來處理多執行緒併發問題Android資料庫執行緒
- python 多執行緒程式設計Python執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Python多執行緒程式設計Python執行緒程式設計
- 轉載_Linux程式與執行緒的區別Linux執行緒
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- Linux C/C++程式設計中的多執行緒程式設計基本概念LinuxC++程式設計執行緒
- 多執行緒程式設計基礎(二)-- 執行緒池的使用執行緒程式設計
- 多執行緒程式設計ExecutorService用法執行緒程式設計
- 29. 多執行緒程式設計執行緒程式設計
- JAVA多執行緒下高併發的處理經驗Java執行緒
- 教小師妹學多執行緒,一個有深度的例子!執行緒
- Linux系統程式設計之訊號中斷處理(上)Linux程式設計
- Java多執行緒—執行緒同步(單訊號量互斥)Java執行緒
- linux中的訊號處理與SROPLinux
- 【Linux網路程式設計-5】多執行緒服務端Linux程式設計執行緒服務端
- Linux下程式與執行緒概念淺析Linux執行緒
- Spring多執行緒事務處理Spring執行緒
- 前端多執行緒處理——async/await前端執行緒AI
- 多執行緒程式設計的核心思想執行緒程式設計
- 多執行緒------執行緒與程式/執行緒排程/建立執行緒執行緒
- PHP 的多程式與執行緒PHP執行緒
- Java多執行緒001——一圖讀懂執行緒與程式Java執行緒
- 多工處理方式之二:多執行緒執行緒
- 深入淺出Win32多執行緒程式設計--之MFC的多執行緒Win32執行緒程式設計
- 深入理解多執行緒程式設計執行緒程式設計
- [02] 多執行緒邏輯程式設計執行緒程式設計
- iOS開發-多執行緒程式設計iOS執行緒程式設計
- Task+ConcurrentQueue多執行緒程式設計執行緒程式設計
- Python——程式、執行緒、協程、多程式、多執行緒(個人向)Python執行緒
- C#多執行緒程式設計實戰1.1建立執行緒C#執行緒程式設計