我试图通过检查waitpid()的结果来确定执行是否失败.但是,即使我运行一个我知道失败的命令并将问题写入stderr,下面的检查也从未注册.这段代码可能有什么问题?
谢谢你的帮助.
pid_t pid; // the child process that the execution runs inside of.
int ret; // exit status of child process.
child = fork();
if (pid == -1)
{
// issue with forking
}
else if (pid == 0)
{
execvp(thingToRun, ThingToRunArray); // thingToRun is the program name, ThingToRunArray is
// programName + input params to it + NULL.
exit(-1);
}
else // We're in the parent process.
{
if (waitpid(pid, &ret, 0) == -1)
{
// Log an …Run Code Online (Sandbox Code Playgroud) 我想知道以下代码是否可以创建僵尸:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
int main(){
int i=1;
pid_t p;
p = fork();
i++;
if(p!=0){
waitpid(p, NULL, 0);
}
printf("%d\n",i);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
因此,父进程调用子进程的waitpid,如果子进程尚未退出,则立即返回.所以,到目前为止,没有僵尸可以出现.但是,如果孩子退出之前
return 0;命令这将是一个僵尸呢?我其实很困惑.在程序终止之前,waitpid应该是最后一行代码吗?任何帮助,将不胜感激.谢谢!
我正在查看系统调用的文档,wait4()并在其手册页中编写了该文档
这些功能已过时;在新程序中使用
waitpid(2)或使用waitid(2)。
因此,我浏览了的文档,waitpid()发现两者之间存在差异。
waitpid()与的功能相同wait4(),但wait4()根据手册页,
另外,在指向的结构中返回有关子级的资源使用信息
rusage。
这两个系统调用定义如下
pid_t wait4(pid_t pid, int *status, int options, struct rusage *rusage);
pid_t waitpid(pid_t pid, int *status, int options);
Run Code Online (Sandbox Code Playgroud)
现在,我还阅读了另一个系统调用,它完成了获取rusage孩子的任务,即getrusage()。
因此,我可以理解,wait4()通过结合使用waitpid()和和,可以做同样的事情getrusage()。
但是,我不了解的是,总是有很强的理由使系统调用过时。但是在这种情况下,感觉功能已被拆分。
waitpid()和getrusage(),我要检查返回值的两倍,这是不是对的情况
wait4()。wait4()来获得rusage一个特定的孩子,但是waitpid()可以将rusage其所有孩子在一起(如果与一起使用RUSAGE_CHILDREN)。如果子进程多于少数,这听起来像是额外的开销。为什么wait4()过时了?看来这使事情变得更加艰难。
我正在编写一个需要在Windows和Linux中运行的perl脚本,它将运行一个进程,如果花费的时间太长,则将其超时,假设退出超时则返回退出代码,并假设exitcode为零且未退出则返回stdout超时。我不需要STDIN或STDERR。我尝试使用IPC::run但无法正常工作。
我最接近的是IPC::Open3和waitpid($pid, WNOHANG)。但是我遇到了障碍。我在Windows和Linux上看到了不同的结果。在下面的代码中,我给出open3了将失败的命令(ping没有任何参数-z)。在Linux上,代码立即返回负退出代码。在Windows上,命令超时。ping google.com -z在Windows命令行上运行会立即返回,告诉我没有这样的参数。为什么``waitpid''返回零?
use strict;
use warnings;
use POSIX ":sys_wait_h";
use IPC::Open3;
my $inFH;
my $outFH;
my @cmd = ("ping", "google.com", "-z");
my $pid = open3( $inFH, $outFH, 0, @cmd);
my $counter=0;
my $waitret;
my $exitcode;
do{
$counter++;
$waitret = waitpid($pid,WNOHANG);
$exitcode = $?;
}while( !$waitret and ($counter < 4_000_000));
if ($counter >= 4_000_000) {
print "Command timed out\n";
kill(9, $pid);
} else {
print "Exit …Run Code Online (Sandbox Code Playgroud) Perl的system()启动一个进程,但打破了父/子关系?
test.pl:
use POSIX;
system("./test.sh &");
my $pid = `ps -C test.sh -o pid=`;
print "pid: -$pid-\n";
waitpid($pid, 0);
Run Code Online (Sandbox Code Playgroud)
test.sh:
while true
do
sleep 1
done
Run Code Online (Sandbox Code Playgroud)
当我运行test.pl时,它会找到并打印一个正确的test.sh. 但是waitpid()返回-1并且test.pl退出.test.pl存在后,test.sh仍在运行.
看起来test.sh不是test.pl的子代,它会破坏waitpid().为什么会发生这种情况以及如何使system()表现出来?这是因为Perl会自动清除孩子吗?如果是,我该如何解决明确等待儿童的一般任务?
更新:
下面的答案建议使用fork/exec.最初的问题是:
从Perl脚本,运行启动服务的命令行实用程序.该实用程序退出但服务仍然存在.
过了一段时间,找到服务的pid并等待它.
虽然它解决了这个问题,但fork/exec并没有解决这个问题.
我知道有关waitpid和超时的许多问题,但他们都通过在警报处理程序中杀死孩子来解决这个问题.
这不是我想要的,我想保持进程运行但是从waitpid发送它.
我试图解决的底层问题是一个守护进程,它有一个处理队列的主循环.任务一次处理一个.
如果任务挂起,整个主循环挂起.绕过这个fork(),waitpid似乎是一个明显的选择.如果任务挂起,循环仍然挂起.
我可以想到我根本不使用waitpid的解决方法,但我必须以另一种方式跟踪运行进程,因为我仍然希望一次处理一个任务并行可能挂起任务.
我甚至可以杀死任务,但我想让它运行来检查究竟出了什么问题.还可以转储一些调试信息的kill处理程序.
无论如何,解决该问题的最方便的方法是在可能的情况下超时waitpid.
编辑:
这就是我使用fork()和waitpid的方式,它可能更清楚孩子的意思.
my $pid = fork();
if ($pid == 0){
# i am the child and i dont want to die
}
elsif ($pid > 0) {
waitpid $pid, 0;
# i am the parent and i dont want to wait longer than $timeout
# for the child to exit
}
else {
die "Could not fork()";
}
Run Code Online (Sandbox Code Playgroud)
编辑:
使用waitpid WNOHANG做我想要的.这种用法是良好的做法还是你会采取不同的做法?
use strict;
use warnings;
use 5.012;
use POSIX …Run Code Online (Sandbox Code Playgroud) 我尝试使用 waitpid() 函数,它需要三个参数,当我实现下面的代码时,我遇到了一些错误,我使用带有三个参数的 wait() 函数,而不是 waitpid() 函数。它工作正常,我不知道它是如何工作的。有谁能解释一下吗??
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
main()
{
pid_t pid;
int p;
if((pid=fork())==0){
printf("Child present\n");
sleep(2);
printf("Child terminated\n");
_exit(0);
}
wait(pid,&p,0);
printf("parent terminated\n");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
但等待函数的语法是
pid_t wait(int *status);
Run Code Online (Sandbox Code Playgroud) 我正在我的系统编程课程中学习forks,execl以及父进程和子进程。令我困惑的一件事是waitpid()和getpid()。有人可以确认或更正我对这两个功能的理解吗?
getpid()将返回调用它的任何进程的进程 ID。如果父级调用它,则返回父级的 pid。对孩子也一样。(pid_t根据联机帮助页,它实际上返回一个 type 值)。
waitpid()似乎更复杂。我知道如果我在父进程中使用它,没有任何标志来防止它阻塞(使用WNOHANG),它将停止父进程,直到子进程终止。waitpid()然而,我有点不确定如何管理这一切。waitpid()也返回pid_t。pid_t waitpid()回报的价值是多少?根据父进程或子进程是否调用它,以及子进程是否仍在运行或已终止,这种情况如何变化?
我需要捕获子进程的返回值..
问题是:使用waitpid()函数我只能捕获返回值的 8 位
WEXITSTATUS(wstatus) 返回子进程的退出状态。这由子进程在调用 exit(3) 或 _exit(2) 或作为 main() 中返回语句的参数指定的状态参数的最低有效 8 位组成。仅当 WIFEXITED 返回 true 时才应使用此宏。
如何捕获从 返回的完整 int 值main()?
编辑:Stackoverflow 强迫我编辑问题,因为它链接了另一个已回答的问题,但这与我的无关!
您好,我是学习系统调用的新手。我目前正在学习 fork() 和 wait() 系统调用。我知道 fork() 创建一个新的子进程。让我困惑的是 wait() 调用。
到目前为止,我的理解是:
(1)当一个进程死亡时,它会进入“僵尸状态”,即它不会释放其PID,而是等待其父进程确认子进程已死亡,然后释放PID
(2) 所以我们需要一种方法来确定子进程何时结束,以便我们不会让任何进程处于僵尸状态
我对以下事情感到困惑:
(1) 当运行一个 C 程序时,我派生了一个新的子进程,如果我不显式调用wait(),当子进程结束时它是在内部完成的吗?因为您仍然可以用 C 语言编写一段代码,在其中运行 fork() 而无需 wait(),并且它似乎工作正常?
(2) wait() 的作用是什么?我知道它返回已终止的子进程的 PID,但这对于释放已终止进程的 PID 有什么帮助/相关呢?
我很抱歉提出这样幼稚的问题,但这是我真的很好奇的事情,而且我在网上找不到任何好的资源!非常感谢您的帮助!