日本a√视频在线,久久青青亚洲国产,亚洲一区欧美二区,免费g片在线观看网站

        <style id="k3y6c"><u id="k3y6c"></u></style>
        <s id="k3y6c"></s>
        <mark id="k3y6c"></mark>
          
          

          <mark id="k3y6c"></mark>

          "); //-->

          博客專欄

          EEPW首頁 > 博客 > 嵌入式Linux:如何監(jiān)視子進程

          嵌入式Linux:如何監(jiān)視子進程

          發(fā)布人:美男子玩編程 時間:2024-10-15 來源:工程師 發(fā)布文章

          在嵌入式Linux系統(tǒng)中,父進程通常需要創(chuàng)建子進程來執(zhí)行特定任務,例如處理網絡請求、執(zhí)行計算任務等。


          監(jiān)視子進程的狀態(tài)不僅可以確保資源的合理利用,還能防止僵尸進程的產生,從而提升系統(tǒng)的穩(wěn)定性和性能。wait()和waitpid()是用于監(jiān)視和管理子進程的關鍵系統(tǒng)調用,而SIGCHLD信號則提供了一種異步通知機制,以便父進程在子進程狀態(tài)發(fā)生變化時采取相應的措施。

          1


          wait()函數(shù)

          wait()系統(tǒng)調用用于讓父進程等待任意一個子進程的終止,并獲取該子進程的終止狀態(tài)信息。


          它執(zhí)行以下功能:

          • 等待子進程終止父進程在調用wait()后會阻塞,直到其任意一個子進程終止為止。

          • 回收子進程資源當子進程終止時,操作系統(tǒng)需要回收它占用的資源,這一過程稱為“收尸”。如果不進行回收,子進程會變?yōu)榻┦M程,占用系統(tǒng)資源。


          僵尸進程是已經終止,但父進程尚未讀取其終止狀態(tài)的子進程。通過調用wait()可以避免系統(tǒng)中積累僵尸進程,影響性能和穩(wěn)定性。


          函數(shù)原型如下:


          #include <sys/types.h>#include <sys/wait.h>pid_t wait(int *status);


          參數(shù)與返回值:

          • status這是一個指向int的指針,用于存儲子進程的退出狀態(tài)。父進程可以通過這個狀態(tài)了解子進程是正常退出還是被信號中止的。如果傳入NULL,則表示不關心子進程的退出狀態(tài),僅僅是等待它終止。

          • 返回值返回已終止的子進程的進程ID;如果調用時沒有子進程存在,wait()返回-1,并將errno設為ECHILD表示沒有子進程可等待。


          函數(shù)行為:

          • 阻塞等待wait()會阻塞調用進程,直到任意一個子進程終止。如果所有子進程都還在運行,wait()將持續(xù)阻塞。

          • 資源回收當子進程終止時,wait()除了獲取子進程的終止狀態(tài),還會回收子進程的資源,避免產生僵尸進程。

          • 處理已終止的子進程如果wait()調用時有子進程已終止,函數(shù)將立即返回,而不會阻塞。


          狀態(tài)檢查,使用宏可以檢查和處理status參數(shù)中存儲的子進程終止狀態(tài):

          • WIFEXITED(status)如果子進程是通過exit()或_exit()正常終止的,則返回true。

          • WEXITSTATUS(status)當WIFEXITED(status)為true時,可以通過該宏獲取子進程的退出狀態(tài),通常是子進程在調用exit()或_exit()時的退出碼。

          • WIFSIGNALED(status)如果子進程因接收到某個信號而異常終止,則返回true。

          • WTERMSIG(status)當WIFSIGNALED(status)為true時,可以通過該宏獲取導致子進程終止的信號編號。

          • WIFSTOPPED(status)如果子進程處于暫停狀態(tài),則返回true。

          • WSTOPSIG(status)當WIFSTOPPED(status)為true時,可以獲取導致子進程暫停的信號編號。

          • WCOREDUMP(status)如果子進程終止時生成了核心轉儲文件,則返回true。


          以下示例展示了如何使用wait()函數(shù)來監(jiān)視子進程的終止狀態(tài)。


          #include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h> int main() {    pid_t pid = fork();  // 創(chuàng)建子進程     if (pid == -1) {        // fork()失敗        perror("fork failed");        exit(EXIT_FAILURE);    } else if (pid == 0) {        // 子進程執(zhí)行代碼        printf("Child process running (PID: %d)...n", getpid());        sleep(2);  // 模擬子進程的執(zhí)行        exit(42);  // 正常退出,并返回狀態(tài)碼42    } else {        // 父進程執(zhí)行代碼        int status;        pid_t child_pid = wait(&status);  // 等待任一子進程終止         if (child_pid > 0) {            // 子進程終止后的處理            if (WIFEXITED(status)) {                printf("Child process %d terminated with status: %dn", child_pid, WEXITSTATUS(status));            } else if (WIFSIGNALED(status)) {                printf("Child process %d was terminated by signal: %dn", child_pid, WTERMSIG(status));            }        } else {            perror("wait failed");        }    }     return 0;}


          在這段代碼中,父進程創(chuàng)建了一個子進程并等待其終止,同時通過status宏獲取子進程的退出狀態(tài)。


          wait()函數(shù)的局限性:

          • 無法指定特定子進程wait()無法讓父進程選擇等待某個特定的子進程,它只能按順序等待下一個終止的子進程。如果父進程同時擁有多個子進程,wait()將隨機處理任意一個子進程的終止。

          • 阻塞等待wait()始終是阻塞的,直到有子進程終止為止。如果父進程需要繼續(xù)處理其他任務,則wait()的阻塞可能導致父進程效率低下。


          2


          waitpid()函數(shù)

          waitpid()函數(shù)提供了更多的控制選項,使得父進程可以選擇性地等待某個特定子進程,或進行非阻塞的等待。


          函數(shù)原型如下:


          #include <sys/types.h>#include <sys/wait.h>pid_t waitpid(pid_t pid, int *status, int options);


          參數(shù):

          • pid指定需要等待的子進程:

            • > 0:等待指定PID的子進程。

            • = 0:等待與調用進程同一進程組的任意子進程。

            • < -1:等待進程組ID等于pid絕對值的所有子進程。

            • = -1:等待任意子進程,與wait()等價。

          • status與wait()的status參數(shù)相同。

          • options可以設置為0或包含以下標志:

            • WNOHANG非阻塞模式。如果沒有子進程終止,立即返回0。

            • WUNTRACED返回因信號停止的子進程的狀態(tài)。

            • WCONTINUED返回收到SIGCONT信號后恢復運行的子進程的狀態(tài)。


          返回值:

          • 成功時,返回已終止或狀態(tài)已改變的子進程的PID。

          • 如果沒有符合條件的子進程,且設置了WNOHANG選項,返回0。

          • 失敗時返回-1,并設置errno。


          waitpid()與wait()的區(qū)別:

          • 等待特定子進程waitpid()允許父進程通過pid參數(shù)指定特定的子進程,而wait()只能等待任意子進程。

          • 非阻塞模式waitpid()支持非阻塞模式(通過WNOHANG),使父進程可以立即返回,而不必等待子進程終止。

          • 支持更多狀態(tài)監(jiān)控waitpid()可以監(jiān)視子進程暫停(WUNTRACED)或恢復運行(WCONTINUED)的狀態(tài),而wait()無法做到這一點。


          示例代碼:


          #include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <stdio.h>#include <stdlib.h> int main() {    pid_t pid = fork();  // 創(chuàng)建子進程     if (pid == -1) {        // fork()失敗        perror("fork failed");        exit(EXIT_FAILURE);    } else if (pid == 0) {        // 子進程執(zhí)行代碼        printf("Child process running (PID: %d)...n", getpid());        sleep(2);  // 模擬子進程工作        exit(42);  // 正常退出,返回狀態(tài)碼42    } else {        // 父進程執(zhí)行代碼        int status;        pid_t child_pid;         // 非阻塞等待子進程        do {            child_pid = waitpid(pid, &status, WNOHANG);  // 非阻塞模式            if (child_pid == 0) {                printf("No child process terminated yet. Doing other work...n");                sleep(1);  // 模擬其他工作            } else if (child_pid > 0) {                if (WIFEXITED(status)) {                    printf("Child process %d terminated with status: %dn", child_pid, WEXITSTATUS(status));                } else if (WIFSIGNALED(status)) {                    printf("Child process %d was terminated by signal: %dn", child_pid, WTERMSIG(status));                }            } else {                perror("waitpid failed");                exit(EXIT_FAILURE);            }        } while (child_pid == 0);         printf("Parent process continues...n");    }     return 0;}



          在這個示例中,父進程可以繼續(xù)處理其他任務,而不必一直阻塞等待子進程的終止。waitpid()的非阻塞模式使得程序更為靈活和高效。 


          3


          SIGCHLD信號

          SIGCHLD是父進程在子進程狀態(tài)發(fā)生變化(如終止或暫停)時收到的信號。通過捕獲SIGCHLD信號,父進程可以實時地檢測到子進程的狀態(tài)變化,并采取相應的行動(例如回收資源)。


          在POSIX標準下,sigaction()系統(tǒng)調用被廣泛用于設置信號處理程序。相比于傳統(tǒng)的signal()函數(shù),sigaction()提供了更多的選項和更好的控制。


          示例代碼:


          #include <sys/types.h>#include <sys/wait.h>#include <unistd.h>#include <signal.h>#include <stdio.h>#include <stdlib.h> void sigchld_handler(int signum) {    int status;    pid_t pid;     // 循環(huán)調用waitpid,以確保處理多個已終止的子進程    while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {        if (WIFEXITED(status)) {            printf("Child process %d terminated with status: %dn", pid, WEXITSTATUS(status));        } else if (WIFSIGNALED(status)) {            printf("Child process %d was terminated by signal: %dn", pid, WTERMSIG(status));        }    }} int main() {    struct sigaction sa;    sa.sa_handler = sigchld_handler;  // 指定信號處理函數(shù)    sigemptyset(&sa.sa_mask);  // 清空阻塞信號集    sa.sa_flags = SA_RESTART;  // 自動重啟被中斷的系統(tǒng)調用    sigaction(SIGCHLD, &sa, NULL);  // 安裝信號處理程序     for (int i = 0; i < 3; i++) {        pid_t pid = fork();  // 創(chuàng)建多個子進程        if (pid == 0) {            // 子進程代碼            printf("Child process %d running...n", getpid());            sleep(2);            exit(42);        }    }     // 父進程的其他工作    while (1) {        printf("Parent process working...n");        sleep(1);    }     return 0;}


          使用sigaction()的優(yōu)點:

          • 自動重啟通過設置SA_RESTART標志,能夠在信號處理完成后自動重啟被中斷的系統(tǒng)調用(如read()、write())。

          • 可靠的信號處理sigaction()避免了傳統(tǒng)signal()函數(shù)的缺陷,確保了信號處理的可靠性和可移植性。


          SIGCHLD信號的常見問題與解決方案:

          • 丟失信號在同時終止多個子進程時,可能會丟失一些SIGCHLD信號。為解決這一問題,可以在信號處理程序中循環(huán)調用waitpid(),直到沒有子進程終止為止。

          • 阻塞的系統(tǒng)調用信號處理可能會中斷一些阻塞的系統(tǒng)調用(如read()或sleep()),導致它們返回錯誤。通過使用sigaction()的SA_RESTART標志可以自動重啟被中斷的調用。


          通過以上內容,開發(fā)者可以根據實際需求選擇合適的方法來監(jiān)視和管理子進程,確保程序運行的穩(wěn)定性和資源的有效利用。


          • 如果只需等待任意一個子進程終止且不關心特定子進程,使用wait()是最簡單的選擇。

          • 如果需要非阻塞地等待特定子進程或需要獲取更多子進程狀態(tài)信息,waitpid()則更為靈活。

          • 在處理多個子進程時,捕獲SIGCHLD信號可以讓父進程更加實時地處理子進程的終止,并在不中斷父進程正常操作的情況下回收子進程資源。


          無論是使用wait()、waitpid()還是SIGCHLD信號處理,確保及時回收子進程的資源是避免僵尸進程的關鍵。

          *博客內容為網友個人發(fā)布,僅代表博主個人觀點,如有侵權請聯(lián)系工作人員刪除。



          關鍵詞: 嵌入式 Linux

          相關推薦

          技術專區(qū)

          關閉