【问题标题】:Stopping a child process at start在启动时停止子进程
【发布时间】:2025-10-23 19:40:01
【问题描述】:

我正在尝试实现一个检查点功能来检查一个进程。我通过分叉一个子进程来做到这一点。但是我需要在启动时暂停子进程。稍后,我们可以通过取消暂停子进程并使父进程自行终止来从检查点重新启动。

这是我为checkpointrestart_from_checkpoint 编写的代码以及如何调用它们的示例。

#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>

pid_t checkpoint();
void restart_from_checkpoint( pid_t pid );

int main( int argc, char *argv[] )
{
  int i;
  pid_t child_pid;
  pid_t parent_pid = getpid();

  for( i = 0; i < 10; i++ )
  {
    if ( i == 4 )
    {
      printf( "%6s: Checkpointing!\n", (getpid() == parent_pid)? "parent":"child" );
      child_pid = checkpoint();
    }

    if ( i == 7 )
    {
      printf( "%6s: Restarting!\n", (getpid() == parent_pid)? "parent":"child" );
      restart_from_checkpoint( child_pid );
    }

    printf( "%6s: i = %d\n", (getpid() == parent_pid)? "parent":"child", i );
  }

  return 0;
}

pid_t checkpoint()
{
    pid_t pid;
    int wait_val;

    switch (pid=fork()) 
    {
    case -1: 
        perror("fork"); 
        break;
    case 0:         // child process starts
        ptrace(PTRACE_TRACEME,0,0,0);
        raise( SIGTRAP ); // Note that this is the solution to first part
                              // of the question, which I added after
                              // asking this question.
        break;  // child process ends
    default:        // parent process starts
        wait(&wait_val);
        return pid;
    }
}

void restart_from_checkpoint( pid_t pid )
{
    ptrace(PTRACE_CONT, pid, NULL, NULL);
    wait(NULL); // I'm just waiting here, but actually 
                //  I need to kill the calling process.
}

调用ptrace(PTRACE_TRACEME,0,0,0)后不知道如何停止子进程。其次,我不知道如何杀死父进程,同时让子进程继续restart_from_checkpoint

最好的办法是使用带有ptrace 的参数,在开始时停止分叉进程,然后以PTRACE_CONT 开始。不幸的是,PTRACE_TRACEME 仅在 exec 函数调用处停止。

【问题讨论】:

  • 现在我已经部分正确了,通过在 ptrace(PTRACE_TRACEME, 0, 0, 0) 之后发出 raise(SIGTRAP)。现在我只需要父进程在调用 restart_from_checkpoint 时退出。
  • 你是用 C 还是 C++ 编译?我这里只看到 C 代码。
  • 我使用 C 还是 C++ 有关系吗?

标签: c linux ptrace


【解决方案1】:

您可以使用 IPC 信号量或 SIGNAL USR1...

【讨论】:

  • 怎么样?我尝试使用 SIGUSR1 和信号但没有运气!您能否详细说明一下或显示一些代码示例。
  • ptrace 中是否有任何参数可用于在开始时停止分叉进程,然后以 PTRACE_CONT 启动。我正在沿着这条线思考。如果有,那我就不用和信号混淆了!
  • 通过在 ptrace(PTRACE_TRACEME, 0, 0, 0) 之后调用 raise( SIGTRAP ) 解决了第一部分。
【解决方案2】:

好的,我找到了解决方案。它现在工作得很好。有兴趣的朋友可以看看这里的代码。

#include <stdio.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <stdlib.h>

pid_t checkpoint();
void restart_from_checkpoint( pid_t pid );

int main( int argc, char *argv[] )
{
  int i;
  pid_t child_pid;
  pid_t parent_pid = getpid();

  for( i = 0; i < 10; i++ )
  {
    if ( i == 4 )
    {
      printf( "%6s: Checkpointing!\n", (getpid() == parent_pid)? "parent":"child" );
      child_pid = checkpoint();
    }

    if ( i == 7 && ( getpid() == parent_pid ) )
    {
      printf( "%6s: Restarting!\n", (getpid() == parent_pid)? "parent":"child" );
      restart_from_checkpoint( child_pid );
    }

    printf( "%6s: i = %d\n", (getpid() == parent_pid)? "parent":"child", i );
  }

  return 0;
}

pid_t checkpoint()
{
    pid_t pid;
    int wait_val;

    switch (pid=fork()) 
    {
    case -1: 
        perror("fork"); 
        break;
    case 0:         // child process starts
        ptrace(PTRACE_TRACEME,0,0,0);
        raise(SIGTRAP);
        break;  // child process ends
    default:        // parent process starts
        wait(&wait_val);
        return pid;
    }
}

void restart_from_checkpoint( pid_t pid )
{
    ptrace(PTRACE_CONT, pid, NULL, NULL);
    ptrace(PTRACE_DETACH, pid, NULL, NULL);
    exit( 1 );
}

【讨论】:

    最近更新 更多