日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

OS / Linux / SIGCHLD 信号

發布時間:2024/10/14 linux 82 豆豆
生活随笔 收集整理的這篇文章主要介紹了 OS / Linux / SIGCHLD 信号 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、SIGCHLD 的產生條件

  • 子進程終止時。
  • 子進程接收到 SIGSTOP 信號停止時。
  • 子進程處在停止態,接收到 SIGCONT 后喚醒時。
  • 也就是說:子進程的運行狀態發生變化就會發送 SIGCHLD 信號;這里的意思時,子進程比較依戀父母,自己發生變化就要給父母說一下。

    二、借助 SIGCHLD 信號回收子進程

    子進程結束運行,其父進程會收到 SIGCHLD 信號。該信號的默認處理動作是忽略,可以捕捉該信號,在捕捉函數中完成子進程狀態的回收。不多說,上代碼:

    #include <iostream> #include <sys/types.h> #include <unistd.h> #include <signal.h> #include <sys/wait.h>void sys_err(const char *p) {perror(p);exit(1); }void do_sig_parent(int signal) {int status;while (waitpid(0, &status, WNOHANG) > 0){if (WIFEXITED(status))std::cout << "子進程正常退出,狀態:" << WEXITSTATUS(status) << std::endl;else if (WIFSIGNALED(status))std::cout << "子進程異常退出,狀態:" << WTERMSIG(status) << std::endl;}return; }int main() {int i = 0;int pid = 0;for (; i < 10; ++i){if ((pid = fork()) == 0)break;else if (pid < 0)std::cout << "fork error" << std::endl;}if (i < 10)std::cout << "子進程的 ID:" << getpid() << std::endl;else{struct sigaction act, oldact;act.sa_handler = do_sig_parent;act.sa_flags = 0;sigemptyset(&act.sa_mask);sigaddset(&act.sa_mask, SIGCHLD);if (sigaction(SIGCHLD, &act, &oldact) < 0)sys_err("sigaction error");while (1){std::cout << "父進程的 ID:" << getpid() << std::endl;sleep(1);}if ((sigaction(SIGCHLD, &oldact, &act)) < 0)sys_err("sigaction error");}sleep(1);return 0; }

    結果:

    子進程的 ID:15185 子進程的 ID:15188 子進程的 ID:15187 子進程的 ID:15189 子進程的 ID:15191 父進程的 ID:15184 子進程的 ID:15192 子進程的 ID:15193 子進程的 ID:15186 子進程的 ID:15190 子進程的 ID:15194 子進程正常退出,狀態:0 子進程正常退出,狀態:0 子進程正常退出,狀態:0 父進程的 ID:15184 子進程正常退出,狀態:0 子進程正常退出,狀態:0 父進程的 ID:15184 子進程正常退出,狀態:0 子進程正常退出,狀態:0 子進程正常退出,狀態:0 子進程正常退出,狀態:0 子進程正常退出,狀態:0 父進程的 ID:15184 父進程的 ID:15184 父進程的 ID:15184 父進程的 ID:15184 父進程的 ID:15184 父進程的 ID:15184

    運行正常,父進程接收到了所有的子進程的退出消息。

    現在我們來提問:可不可以將程序中,捕捉函數內部的 while 替換為 if,即將代碼?while((waitpid(0, &status, WNOHANG) > 0)) 換為 if((waitpid(0, &status, WNOHANG) > 0))?為什么?

    答案:不可以,修改下并運行:

    子進程的 ID:15384 子進程的 ID:15385 子進程的 ID:15386 子進程的 ID:15388 父進程的 ID:15383 子進程的 ID:15390 子進程的 ID:15393 子進程的 ID:15387 子進程的 ID:15392 子進程的 ID:15389 子進程的 ID:15391 子進程正常退出,狀態:0 父進程的 ID:15383 子進程正常退出,狀態:0 父進程的 ID:15383 子進程正常退出,狀態:0 父進程的 ID:15383 父進程的 ID:15383 父進程的 ID:15383 父進程的 ID:15383 父進程的 ID:15383 父進程的 ID:15383

    可以發現,有 7 個子進程的退出狀態父進程沒有捕獲到,原因是 if 只執行一次回收(因為到了那兒說明父進程收到信號了,也就是說一定有子進程死掉了。)但是若是某一個時刻有多個子進程同時死了,那么依據信號不進行排隊的原理,就只有其中一個信號被處理,其他的被忽略。但是 while 就不一樣了,就算同時來多個信號,但是 while 時循環執行,雖然信號處理先后順序不一樣,但是每個信號都會被處理啊(非阻塞的 waitpid 函數)。

    所以啊,當有多個子進程時,回收的時候用循環,不要用 if。

    ?

    參考:https://blog.csdn.net/weixin_30752699/article/details/97366496

    ?

    (SAW:Game Over!)

    ?

    總結

    以上是生活随笔為你收集整理的OS / Linux / SIGCHLD 信号的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。