中断调用函数 popen 的进程

Posted

技术标签:

【中文标题】中断调用函数 popen 的进程【英文标题】:Interrupt a process calling the function popen 【发布时间】:2016-12-29 16:58:37 【问题描述】:

我需要实现一个子进程来执行一个文件并发送执行结果,这2个进程将与一个共享内存段进行通信。

我的问题是我想在 10 秒后杀死调用 popen 的子进程,但函数 popen 忽略了信号。

这是我的代码(不包括共享内存段):

void kill_child(int sig)

 kill(child_pid,SIGKILL);
printf("processus killed \n");



/*code....*/

signal(SIGALRM,(void (*)(int))kill_child);

if(fork()==0)
                res.buffer=true;
                FILE * fd;
                char cmd[BUFFER_SIZE],output[BUFFER_SIZE];
                strcpy(cmd,"./");
                strcat(cmd,res.filepath);
                system(cmd);
                if((fd=popen(cmd,"r"))== NULL)
                    exit(1);
                else 
                    res.status=200;


                strcpy(output,"");
                while(fgets(buf,sizeof(buf)-1,fd))
                    strcat(output,buf);

                if(pclose(fd))
                    exit(1);

                strcat(res.customhtml,output);
                res.buffer=true;


                int err = sendResponse(res,args->client_fd);
                if (err < 0) on_error("failed!\r\n");



                exit(0);


  

 else

               int status;
               alarm(10);
               waitpid(-1,&status,0);
               printf("status %d _n);

如何让子进程可中断?

谢谢

【问题讨论】:

你的代码有没有到达 popen 调用?您也在使用 system 执行命令,因此它会等到该命令完成运行后再继续。 是的,它到达了 popen 调用,我添加系统只是为了测试,但如果尝试执行一个文件,例如 sleep(12);超过 10 秒,进程不会停止执行 如果你用 sleep(12) 替换 popen,你的代码会按预期工作吗? 是的,当我更换它时它可以工作。 【参考方案1】:

首先,您需要将子 PID 实际存储到 child_pid 中。它是从 fork 为父进程返回的,因此将您的 fork 调用更改为

child_pid = fork();
if(child_pid == 0)
  
...

否则,您的 kill 调用将被传递一个随机值。幸运的是,它似乎默认为 0,这意味着 kill 意味着杀死同一进程组中的所有进程,因此您的子进程被杀死。

其次,与其调用 popen(),不如使用(例如)execvp() 自己调用可执行文件,并让父级使用您自己创建的管道读取输出...

int fds[2];

pipe(fds);
child_pid = fork();
if(child_pid == 0)
  
  char *cmd[]="mycmd",NULL;

  /* Replace stdout with the output of the pipe and close the original */
  dup2(fds[1],1);
  close(fds[0]);
  close(fds[1]);
  execvp(cmd[0],cmd);
  
else
  
  close(fds[1]);
  alarm(10);
  while(...)
     
     read(fds[0],....);
     if(waitpid(child_pid,&status,WNOHANG))
         
         ....
         
     
  

这样,您只有一个运行可执行文件的子进程,并且您可以了解它何时以及如何退出。

【讨论】:

我认为你应该接受答案,如果它有效:)

以上是关于中断调用函数 popen 的进程的主要内容,如果未能解决你的问题,请参考以下文章

IPC通信基于管道的popen和pclose函数

Socket进程处理被中断的系统调用及Accept函数返回EINTR错误处理

课程学习总结报告

popen()/pclose()阻塞性问题验证

驱动:中断中断处理程序中断上下文中处理延时及一些函数的调用规则(调IIC中断驱动有感)

结合中断上下文切换和进程上下文切换分析Linux内核的一般执行过程