system阻塞SIGCHLD信號原因

system阻塞SIGCHLD信號原因

標簽: c
198人閱讀 評論(0) 收藏 舉報
分類:

代碼1:APUE10.18節的system函數源代碼?
int system(const char *cmdstring) /* with appropriate signal handling */
{
? ? pid_t? ?? ?? ?? ?? ?pid;
? ? int? ?? ?? ?? ?? ???status;
? ? struct sigaction? ? ignore, saveintr, savequit;
? ? sigset_t? ?? ?? ?? ?chldmask, savemask;
? ? ……
? ? sigemptyset(&chldmask);? ?? ?? ?/* now block SIGCHLD */
? ? sigaddset(&chldmask, SIGCHLD);
? ? if (sigprocmask(SIG_BLOCK, &chldmask, &savemask)?
? ?? ???return(-1);

? ? if ((pid = fork())?
? ?? ???status = -1;? ? /* probably out of processes */
? ? } else if (pid == 0) {? ?? ?? ? /* child */
? ?? ???……
? ?? ???sigprocmask(SIG_SETMASK, &savemask, NULL);

? ?? ???execl("/bin/sh", "sh", "-c", cmdstring, (char *)0);
? ?? ???_exit(127);? ???/* exec error */
? ? } else {? ?? ?? ?? ?? ?? ?? ?? ?/* parent */
? ?? ? while (waitpid(pid, &status, 0)?
? ?? ?? ???if (errno != EINTR) {
? ?? ?? ?? ?? ?status = -1; /* error other than EINTR from waitpid() */
? ?? ?? ?? ?? ?break;
? ?? ?? ???}
? ? }
? ? ……
? ? if (sigprocmask(SIG_SETMASK, &savemask, NULL)?
? ?? ???return(-1);

? ? return(status);}
如果該函數的調用者在其SIGCHLD信號處理函數中調用了waitpid函數來獲得任意子進程的終止狀態,且在fork之前沒有阻塞SIGCHLD信號,則子進程結束,父進程執行SIGCHLD信號處理函數且得到了子進程的終止狀態。而該函數中的waitpid函數由于沒有得到其創建的子進程的終止狀態而出錯。

定義了一個函數,函數中fork了一個子進程,并且定義的函數要得到關于子進程的一些信息,例如子進程ID、子進程終止狀態等,而該函數的調用者所注冊的SIGCHLD信號處理函數會影響定義的這個函數獲取這些信息,因此為了避免該函數在獲取這些信息之前,由于子進程終止觸發SIGCHLD信號處理函數先執行,在fork之前都將SIGCHLD信號阻塞了,在函數獲取了相關信息后,才對SIGCHLD信號接觸阻塞。?


接下來我們以代碼1為例完整的解釋一下阻塞SIGCHLD信號的原因:

在一個進程終止或停止時,SIGCHLD信號被送給其父進程。按系統默認,將忽略此信號。如果父進程希望了解其子進程的這種狀態改變,則應捕捉此信號。信號捕捉函數中通常要調用wait函數以取得子進程ID和其終止狀態。

一般的,父進程在生成子進程之后會有兩種情況:一是父進程繼續去做別的事情;另一是父進程什么都不做,一直在wait子進程退出。

SIGCHLD信號就是為第一種情況準備的,它讓父進程去做別的事情,而只要父進程注冊了處理該信號的函數,在子進程退出時就會調用該函數,在函數中wait子進程得到終止狀態之后再繼續做父進程的事情。


我們先來寫一個function_model函數模型,如下所示:
int function_model(…) {? ? pid_t? ?? ?? ?? ?? ?pid;? ? int? ?? ?? ?? ?? ???status;? ? ……? ? if ((pid = fork())? ?? ?? ?status = -1;? ?? ???} else if (pid == 0) {? ?? ?? ? /* child */? ?? ? ……? ? } else {? ?? ?? ?? ?? ?? ?? ?? ?/* parent */? ?? ? while (waitpid(pid, &status, 0)? ?? ?? ?? ?if (errno != EINTR) {? ?? ?? ?? ?? ?status = -1;? ?? ?? ?? ?? ? break;? ?? ?? ???}? ? }? ?? ???……? ? return(status);}


當我們定義了一個具有function_model函數模型結構的函數時,應該在fork之前將SIGCHLD信號阻塞,fork之后,父子進程的SIGCHLD信號都是被阻塞的。子進程在進行任何的操作之前,應該將SIGCHLD恢復至原來的設置。父進程則應該在waitpid函數之后,將SIGCHLD恢復至原來的設置。


即這種類型的函數的正確的格式為:

int function_model(…)?
{
? ? pid_t? ?? ?? ?? ?? ?pid;
? ? int? ?? ?? ?? ?? ???status;
? ? sigset_t? ?? ?? ?? ?chldmask, savemask;
? ? ……
? ? sigemptyset(&chldmask);? ?? ?? ?/* now block SIGCHLD */
? ? sigaddset(&chldmask, SIGCHLD);
? ? if(sigprocmask(SIG_BLOCK, &chldmask, &savemask)?
? ?? ???return(-1);

? ? if ((pid = fork())?
? ?? ???status = -1;? ??
} else if (pid == 0) {? ?? ?? ? /* child */

sigprocmask(SIG_SETMASK, &savemask, NULL);
? ?? ? ……
? ? } else {? ?? ?? ?? ?? ?? ?? ?? ?/* parent */
? ?? ? while (waitpid(pid, &status, 0)?
? ?? ?? ???if (errno != EINTR) {
? ?? ?? ?? ?? ?status = -1;?
? ?? ?? ?? ?? ?break;
? ?? ?? ???}
? ? }
? ? ……
if(sigprocmask(SIG_SETMASK, &savemask, NULL)?
? ? return(-1);
? ? return(status);
}

父進程阻塞SIGCHLD信號的原因在于:如果function_model函數的調用者caller在調用function_model之前,注冊了SIGCHLD信號的處理函數sigchld_handler,且sigchld_handler函數中調用了waitpid函數等待任意子進程結束,如下所示:

void sigchld_handler(int signo)
{
? ? pid_t pid;
? ? int status;
? ? while((pid=waitpid(-1,&status,WNOHANG))>0)
? ? {
? ?? ???……
}
return ;
}

? ? 若我們沒有阻塞SIGCHLD信號,則當function_model函數中fork的子進程結束時,會向父進程發送SIGCHLD信號,則其信號處理函數sigchld_handler被調用,并在sigchld_handler函數中調用了waitpid得到了這個子進程的退出狀態,然后釋放掉其占用的進程表等其它資源。返回到function_model函數中繼續執行,由于其創建的子進程的退出狀態已經被獲取,內核不再保存其退出狀態,所以其中調用的waitpid函數由于無法得到其退出狀態而出錯,并將status設置為-1。
? ? 若我們阻塞了SIGCHLD信號,則當function_model函數中fork的子進程結束時,內核會向父進程發送SIGCHLD信號,但SIGCHLD信號被阻塞而不遞送給父進程,即處于未決狀態,因此function_model函數中的waitpid就能正確得到這個子進程的退出狀態。當解除對SIGCHLD信號的阻塞時,SIGCHLD信號會被遞交給父進程,引發父進程調用sigchld_handler函數,由于在function_model函數中以調用waitpid獲取了function_model函數創建的子進程的退出狀態,內核不再保存其終止信息,所以sigchld_handler中的waitpid也不會的到其退出狀態。

? ? 下面是Advanced Programming in the UNIX® Environment: Second Edition(APUE)中的解釋:
POSIX.1 states that if wait or waitpid returns the status of a child process while SIGCHLD is pending, then SIGCHLD should not be delivered to the process unless the status of another child process is also available. None of the four implementations discussed in this book implements this semantic. Instead, SIGCHLD remains pending after the system function calls waitpid; when the signal is unblocked, it is delivered to the caller. If we called wait in the sig_chld function in?
Figure 10.26
, it would return 1 with errno set to ECHILD, since the system function already retrieved the termination status of the child.

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

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

相關文章

設計模式6---(單例模式的概念及其實現(懶漢式和餓漢式),線程安全)

單例模式 單例模式的概念 單例模式是一種對象創建型模式,使用單例模式,可以保證為一個類只生成唯一的實例對象。也就是說,在整個程序空間中,該類只存在一個實例對象。 GoF 對單例模式的定義是:保證一個類、只有一個實…

C語言解析http請求表單內容

[1].[文件] cgi.h ~ 405B 下載(105) 跳至 [1] [2] [3] [4] [5] [6] [7] [8] ?123456789101112131415161718192021222324252627#ifndef CGI_H#define CGI_H#include <stdio.h>#include <string.h>#include <stdlib.h>typedef struct Node{char *…

centos給用戶添加sudo權限

linux給用戶添加sudo權限&#xff1a; 有時候&#xff0c;linux下面運行sudo命令&#xff0c;會提示類似&#xff1a; xxxis not in the sudoers file. This incident will be reported. 這里&#xff0c;xxx是用戶名稱&#xff0c;然后導致無法執行sudo命令&#xff0c;這時候…

php手冊

http://www.php100.com/manual/php/ http://www.kuqin.com/php5_doc/

套接字編程---2(TCP套接字編程的流程,TCP套接字編程中的接口函數,TCP套接字的實現,TCP套接字出現的問題,TCP套接字多進程版本,TCP套接字多線程版本)

TCP模型創建流程圖 TCP套接字編程中的接口 socket 函數 #include <sys/types.h> /* See NOTES */ #include <sys/socket.h> int socket(int domain, int type, int protocol); domain: AF_INET 這是大多數用來產生socket的協議&#xff0c;使用TCP或UDP來傳輸&…

安全關注

http://yttitan.blog.51cto.com/70821/1576365

Linux中netstat工具詳解

簡介 Netstat 命令用于顯示各種網絡相關信息&#xff0c;如網絡連接&#xff0c;路由表&#xff0c;接口狀態 (Interface Statistics)&#xff0c;masquerade 連接&#xff0c;多播成員 (Multicast Memberships) 等等。 常見參數 -a (all)顯示所有選項&#xff0c;默認不顯示…

網絡基礎 2-1(應用層,HTTP三點注意,HTTP協議格式, 最簡單的HTTP服務器)

應用層 應用層 負責應用程序之間的數據溝通-----協議都是用戶自己定的 自定制協議&#xff1a; 結構化數據傳輸 序列化&#xff1a; 將數據對象以指定的協議&#xff08;數據格式&#xff09;進行可用于持久化存儲或者數據傳輸時的數據組織 例如在分布式的系統中&#xf…

正則表達式 學習

http://regexr.com/ 在線匹配 http://c.biancheng.net/cpp/html/1434.html 查詢網址

網絡基礎2-2(傳輸層,端口,詳談UDP)

傳輸層 負責數據能夠從發送端傳輸接收端. 端口號 端口號(Port)標識了一個主機上進行通信的不同的應用程序;在TCP/IP協議中, 用 “源IP”, “源端口號”, “目的IP”, “目的端口號”, “協議號” 這樣一個五元組來標識一個通信(可以通過 netstat -n查看);一個端口只能被一個…

中文rfc文檔路徑

http://man.chinaunix.net/develop/rfc/default.htm

網絡基礎2-3(TCP協議,三次握手,四次揮手,TIME_WAIT狀態的作用,TCP如何保證可靠傳輸,TCP連接中狀態轉化,滑動窗口,流量控制,快速重傳,擁塞窗口,延遲應答,捎帶應答,粘包問題)

TCP協議 TCP協議概念 TCP全稱為 “傳輸控制協議(Transmission Control Protocol”). 人如其名, 要對數據的傳輸進行一個詳細的控制 TCP協議格式 1. 源/目的端口號: 表示數據是從哪個進程來, 到哪個進程去; 2. 32位序號/32位確認號: 后面詳細講; 3. 4位TCP報頭長度: 表示該…

超時設置

//read操作加上超時時間。1 int read_timeout(int fd, void *buf, uint32_t count, int time)2 {3 if(time > 0) {4 fd_set rSet;5 FD_ZERO(&rSet);6 FD_SET(fd, &rSet);7 8 struct timeval timeout;9 memset(&tim…

字符串題目 1 --------判斷兩個字符串是否為旋轉詞

題目描述 如果一個字符串為str&#xff0c;把字符串的前面任意部分挪到后面形成的字符串交str的旋轉詞。比如str“12345”&#xff0c;str的旋轉串有“12345”、“45123”等等。給定兩個字符串&#xff0c;判斷是否為旋轉詞。 輸入描述: 輸出包含三行&#xff0c;第一個兩個…

2021-03-04

為什么nginx轉發后端默認使用1.0而不是1.1 在 Nginx 的官網文檔中&#xff0c;有這樣一個指令&#xff1a; Syntax: gzip_http_version 1.0 | 1.1; Default: gzip_http_version 1.1; Context: http, server, location Sets the minimum HTTP version of a request required to…

字符串題目---2判斷兩個字符串是否為變形詞

題目描述 給定兩個字符串str1和str2&#xff0c;如果str1和str2中出現的字符種類出現的一樣且每種字符出現的次數也一樣&#xff0c;那么str1和str2互為變形詞。請判斷str1和str2是否為變形詞 輸入描述: 輸入包括3行&#xff0c;第一行包含兩個整數n&#xff0c;m(1 \leq n,…

設計模式7----代理模式

代理模式 概念 Proxy 模式又叫做代理模式&#xff0c;是結構型的設計模式之一&#xff0c;它可以為其他對象提供一 種代理&#xff08;Proxy&#xff09;以控制對這個對象的訪問。 所謂代理&#xff0c;是指具有與代理元&#xff08;被代理的對象&#xff09;具有相同的接口的…

網絡基礎3-1(細談IP協議頭, 網絡層,子網劃分,路由選擇,數據鏈路層,以太網幀格式,MAC地址,再談ARP協議)

IP協議 IP協議頭格式 4位版本號(version): 指定IP協議的版本, 對于IPv4來說, 就是44位頭部長度(header length): IP頭部的長度是多少個。32bit, 也就是 length * 4 的字節數. 4bit表示大 的數字是15, 因此IP頭部大長度是60字節8位服務類型(Type Of Service): 3位優先權字段(已…

c++常見并且必須記住的問題

一、基礎知識 基本語言 1、說一下static關鍵字的作用 ?2、說一下C和C的區別 3、說一說c中四種cast轉換 4、請說一下C/C 中指針和引用的區別&#xff1f; 5、給定三角形ABC和一點P(x,y,z)&#xff0c;判斷點P是否在ABC內&#xff0c;給出思路并手寫代碼 6、怎么判斷一個…

網絡中典型協議--(DNS,輸入url后, 發生的事情. ,ICMP,NAT)

DNS&#xff08;Domain Name System&#xff09; DNS是一整套從域名映射到IP的系統 域名服務器發展背景 TCP/IP中使用IP地址和端口號來確定網絡上的一臺主機的一個程序. 但是IP地址不方便記憶. 于是人們發明了一種叫主機名的東西, 是一個字符串, 并且使用hosts文件來描述主機…