检查一个分叉的孩子是不是已经在 perl 中执行
Posted
技术标签:
【中文标题】检查一个分叉的孩子是不是已经在 perl 中执行【英文标题】:Checking if a forked child has exec'ed yet in perl检查一个分叉的孩子是否已经在 perl 中执行 【发布时间】:2012-03-30 19:06:57 【问题描述】:我在 perl 脚本中有以下设计:
my $child_pid = fork;
if( ! $child_pid )
# do some stuff...
exec( $user_specified_command );
else
# wait for child to exit
waitpid( $child_pid, 0 );
# Continue with the script
我有兴趣在子级执行时在父级中收到警报,以便我可以获得有关$user_specified_command
的一些详细信息(具体来说,使用lsof
来确定标准输出是否被重定向到常规文件) .结果会是这样的:
my $child_pid = fork;
if( ! $child_pid )
# do some stuff...
exec( $user_specified_command );
else
# wait until the child exec's
wait_child_exec();
# do some stuff...
# wait for child to exit
waitpid( $child_pid, 0 );
# Continue with the script
我可以循环并 grep ps
输出直到名称更改,但似乎 exec 是一个足够严重的事件,有更好的方法。
【问题讨论】:
交换孩子和父母的角色会不会更容易?毕竟父母有孩子的PID,可以在此基础上发出信号。 如果我希望“这个”进程在执行之前发送信号,那么操作系统是否有可能尚未处理执行,而我的 perl 内容可能会过早发生? 是的,完全正确。我应该想到的,但没有。因此,根据您的建议,出现了另一个想法:您可以编写一个围绕$user_specified_command
的包装器吗?包装器将接收两个命令行参数:首先,它将接收“this”进程的 PID,以便它可以发送所需的信号;其次,它会收到$user_specified_command
,这样它就知道它正在包装哪个命令。如果这不能解决时间问题,那么我的方法很糟糕。请指教。
【参考方案1】:
对此的一种通用方法是在父级中创建一个由子级继承的管道,并让父级阻塞(或轮询)管道的读取端。
假设子进程有 FD_CLOEXEC,或者更好的是,$^F
的合适值,子进程对 exec()
的调用将关闭管道的写入端并为父进程生成一个 EOF:
# Run a command in a child process, returning to the parent only after
# the child process has called exec'd or, failing that, terminated.
#
# WARNING - this code not rigorously tested
#
sub spawn_patiently
my ($rd, $wr);
return unless pipe($rd, $wr);
# XXX This assumes $^F is less than fileno($wr)
# In practice, you'd want it to be less than fileno($rd), too
my $pid = fork();
return unless defined $pid;
if (! $pid)
exec @_;
die "exec: $!";
# parent - wait for child to exec
close($wr);
read($rd, my $dummy, 1);
1;
【讨论】:
以上是关于检查一个分叉的孩子是不是已经在 perl 中执行的主要内容,如果未能解决你的问题,请参考以下文章