2013-10-17 59 views
1

嗨我有一个简单的功能,我创建一个子进程和父进程。为什么SIGUSR1会杀死我的dd子进程?

子进程假设运行dd if =/some/file of =/somedisk。 父进程假设在循环中运行(直到孩子存在),并发送信号SIGUSR1,强制子进程中的dd报告进度数据。

当然,我有管道,我将stdio和stderr从孩子重定向到父母。 (这个我用在其他功能,它工作正常)

我的问题是: 1.我没有得到任何东西在我的stderr; 2.一旦我发送SIGUSR1,进程就会以某种方式退出。

if(my_pid>0) //The parent part 
      { 

      close(FD_pipe_stdout[1]);// Parent process closes output side of the pipe 
      close(FD_pipe_stderr[1]);// Parent process closes output side of the pipe        
      while(0==waitpid(my_pid, &my_pid_status, WNOHANG)) 
       { 
       kill(my_pid, SIGUSR1); 
       sleep(1); 
       //read(FD_pipe_stderr[0], pipe_error,PIPE_MAX_SIZE); // Read in a string from the stderror 
       //puts(pipe_error); 

       } 
      puts("going out"); 
      read(FD_pipe_stdout[0], pipe_output,PIPE_MAX_SIZE); // Read in a string from the pipe's input side 

      close(FD_pipe_stdout[0]);//on the end close the other side of pipe 
      close(FD_pipe_stderr[0]);//on the end close the other side of pipe 
      }   
    else 
      { // The child part 
      close(FD_pipe_stdout[0]);/* Child process closes input side of the pipe */ 
      close(FD_pipe_stderr[0]);/* Child process closes input side of the pipe */ 
      dup2(FD_pipe_stdout[1],1); //redirect the stdout(1) to the fd_pipe and then close the sdtout 
      dup2(FD_pipe_stderr[1],2);//redirect also stderr to the pipe 
      system(dd if=/image.img of=/dev/sda); 
      close(FD_pipe_stdout[1]); //on the end close the other side of pipe 
      close(FD_pipe_stderr[1]); //on the end close the other side of pipe 
      exit(0); 
      } 

我在屏幕上看到父母正在从while循环出去,我不明白为什么。

在此先感谢

+0

请参阅答案http://stackoverflow.com/questions/19417272/pthreads-and-signal-handling-c-ending-early?noredirect=1#comment28784971_19417272 –

+0

我的猜测是'system(“dd .. 。“)是问题所在。这使用了可能不会捕获SIGUSR1的shell。试试'execlp(“dd”,“if = ...”,“of = ...”,NULL)'。 –

+0

'system(dd if =/image.img of =/dev/sda);'看起来这里有一些引号缺失。 – wildplasser

回答

4

system()创建一个子进程来运行指定的命令,所以你真的在这里三个过程:

  1. 父进程(具有环路)
  2. 的子过程(叫system()
  3. dd过程

您正在发信号通知子进程而不是dd进程。 SIGUSR1默认会导致一个进程退出,所以你正在杀死子进程。

为了解决这个问题,你可以运行使用的exec功能之一DD,而不是调用system()

{ // The child part 
    close(FD_pipe_stdout[0]); 
    close(FD_pipe_stderr[0]); 
    dup2(FD_pipe_stdout[1],1); 
    dup2(FD_pipe_stderr[1],2); 
    execlp("dd", "dd", "if=/image.img", "of=/dev/sda", NULL); 
    perror("exec failed"); 
    exit(1); 
} 

现在你只有两个进程,因为子进程成为DD过程。当父母发信号给孩子时,信号将变为dd

请注意,这里有一个竞争条件。父进程可以在启动dd之前发送SIGUSR1信号,并设置其信号处理程序。为了健壮,你应该以某种方式处理这个问题。

+3

请注意,'execlp()'需要一个最终的'NULL'参数。 –

+0

@ martin-r固定,谢谢。 – Kenster

+0

谢谢Kenster。完美的作品! – Gregorek