[英]Differentiate processes states using waitpid and WNOHANG
在構建 shell 程序時,我遇到了識別進程狀態的問題。 我面臨的問題的描述是我有一個子進程列表,我正在嘗試使用waitpid
和WNOHANG
找出他們的 state 。 我希望區分 3 種狀態: TERMINATED
、 RUNNING
和SUSPENDED
。 (在下面的代碼中定義)我希望將進程狀態更改為上述三個之一,但是現在這個 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();
}
另外,請注意:
WUNTRACED
和WCONTINUED
:除非您使用ptrace()
跟蹤孩子或使用WUNTRACED
標志,否則WIFCONTINUED()
WIFSTOPPED()
發生,除非使用WCONTINUED
,否則 WIFCONTINUED() 不會發生。code
和ppid
變量應該是pid_t
,而不是int
( ppid
變量似乎也不需要)。 在任何情況下,請考慮為SIGCHLD
添加信號處理程序並在那里更新子狀態。 您的程序將為每個終止/停止/恢復的孩子收到一個SIGCHLD
。 它更簡單也更快(不需要在每個子進程上連續調用waitpid()
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.