检查一个分叉的孩子是不是已经在 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 中执行的主要内容,如果未能解决你的问题,请参考以下文章

从另一个环境调用 Perl 在后台

当另一个孩子完成时如何退出一个子进程

如何在 Perl 中检查多个变量是不是为空

在一个父母中分叉多个孩子

解析Perl 5并检查语法树

检查是不是有孩子在场?如果仅存在则执行特定方法