gpt4 book ai didi

c - 使用 waitpid 和 WNOHANG 区分进程状态

转载 作者:行者123 更新时间:2023-12-04 16:18:22 26 4
gpt4 key购买 nike

在构建 shell 程序时,我遇到了识别进程状态的问题。我面临的问题的描述是,我有一个子进程列表,我正在尝试使用 waitpidWNOHANG 来弄清楚它们的状态。我想区分 3 种状态:TERMINATEDRUNNINGSUSPENDED。 (如以下代码中所定义)我希望将进程状态更改为上述三种状态之一,但是现在此函数使正在运行的进程状态为 terminated,并且此函数也无法识别挂起的进程。我想知道我做错了什么以及应该如何编写函数 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... 的返回值,并修复其余的检查。

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:WIFSTOPPED() 不会发生,除非您使用 ptrace 跟踪 child () 或您使用了 WUNTRACED 标志,除非使用 WCONTINUED,否则 WIFCONTINUED() 不会发生。
  2. codeppid 变量应该是 pid_t,而不是 int(ppid 变量似乎也不需要)。

无论如何,请考虑为 SIGCHLD 添加信号处理程序并在那里更新子状态。对于每个终止/停止/resuems 的 child ,您的程序将收到一个 SIGCHLD。它更简单也更快(不需要在每个子进程上连续调用 waitpid())。

关于c - 使用 waitpid 和 WNOHANG 区分进程状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61669640/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com