簡體   English   中英

使用 waitpid 和 WNOHANG 區分進程狀態

[英]Differentiate processes states using waitpid and WNOHANG

在構建 shell 程序時,我遇到了識別進程狀態的問題。 我面臨的問題的描述是我有一個子進程列表,我正在嘗試使用waitpidWNOHANG找出他們的 state 。 我希望區分 3 種狀態: TERMINATEDRUNNINGSUSPENDED (在下面的代碼中定義)我希望將進程狀態更改為上述三個之一,但是現在這個 function 使正在運行的進程狀態被terminated ,並且這個 function 也不能識別暫停的進程。 我想知道我做錯了什么以及應該如何編寫 function updateProcessList來實現它?

#define TERMINATED  -1
#define RUNNING 1
#define SUSPENDED 0

typedef struct process{
    cmdLine* cmd;                     /* the parsed command line*/
    pid_t pid;                        /* the process id that is running the command*/
    int status;                       /* status of the process: RUNNING/SUSPENDED/TERMINATED */
    struct process *next;             /* next process in chain */
} process;

void updateProcessList(process **process_list) {
    process *p = *process_list;
    int code = 0, status = 0,pidd = 0;
    while (p) {
        pidd = p->pid;
        code = waitpid(pidd, &status, WNOHANG);
        if (code == -1) {            /* child terminated*/
            p->status = TERMINATED;
        } else if(WIFEXITED(status)){
            p->status = TERMINATED;
        }else if(WIFSTOPPED(status)){
            p->status = SUSPENDED;
        }
        p = p->next;
    }
}

來自man 2 waitpid

 RETURN VALUE waitpid(): on success, returns the process ID of the child whose state has changed; if WNOHANG was specified and one or more child(ren) specified by pid exist, but have not yet changed state, then 0 is returned. On error, -1 is returned.

您應該檢查返回值0 ... 並修復檢查的 rest。

code = waitpid(ppid, &status, WNOHANG | WUNTRACED | WCONTINUED);

if (code == -1) {
    // Handle error somehow... 
    // This doesn't necessarily mean that the child was terminated!
    // See manual page section "ERRORS".

    if (errno == ECHILD) {
        // Child was already terminated by something else.
        p->status = TERMINATED;
    } else {
        perror("waitpid failed");
    }
} else if (code == 0) {
    // Child still in previous state.
    // Do nothing.
} else if (WIFEXITED(status)) {
    // Child exited.
    p->status = TERMINATED;
} else if (WIFSIGNALED(status)) {
    // Child killed by a signal.
    p->status = TERMINATED;
} else if (WIFSTOPPED(status)) {
    // Child stopped.
    p->status = SUSPENDED;
} else if (WIFCONTINUED(status)) {
    // This branch seems unnecessary, you should already know this
    // since you are the one that should kill(pid, SIGCONT) to make the
    // children continue.
    p->status = RUNNING; 
} else {
    // This should never happen!
    abort();
}

另外,請注意:

  1. 我在標志中添加了WUNTRACEDWCONTINUED :除非您使用ptrace()跟蹤孩子或使用WUNTRACED標志,否則WIFCONTINUED() WIFSTOPPED()發生,除非使用WCONTINUED ,否則 WIFCONTINUED() 不會發生。
  2. codeppid變量應該是pid_t ,而不是intppid變量似乎也不需要)。

在任何情況下,請考慮為SIGCHLD添加信號處理程序並在那里更新子狀態。 您的程序將為每個終止/停止/恢復的孩子收到一個SIGCHLD 它更簡單也更快(不需要在每個子進程上連續調用waitpid() )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM