首页 > 学技术 > 技术网文 > C/C++ > 正文

[保留] 杀死所有子进程的 两种方法


来源 chinaunix.net kuqin整理


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <sys/types.h>
      4 #include <signal.h>
      5 #include <unistd.h>
      6
      7 .......
     55         return 0;
     56 }
     57


这里代码不够完美,删掉了

后面有比较好的,可用的代码

有兴趣的请自行取阅


最终解决问题请见16楼和17楼


[url=http://bbs.chinaunix.net/viewthread.php?tid=907131&pid=6524793&page=2&extra=page%3D1#pid6524793]http://bbs.chinaunix.net/viewthread.php?tid=907131&pid=6524793&page=2&extra=page%3D1#pid6524793

[ 本帖最后由 net_robber 于 2007-3-13 20:17 编辑 ]



 新手上路2世 回复于:2007-03-09 14:11:05

楼主的钻研精神令人敬佩!!! 继续关注


 net_robber 回复于:2007-03-09 14:14:47

谢谢


 isnowran 回复于:2007-03-09 14:42:29

二位的观点可能有点误区
1。杀掉父进程,子进程并不会被杀掉
引用:
考虑两个问题
1、自进程已经被干掉了,但是楼主没有waitpid(),所以还以为子进程还再。我见过有人这样
2、杀掉父进程,子进程不就被干掉了么????



2。子进程会继承父进程的信号屏蔽
引用:
不是这样的! 子进程是不会继承父进程的信号设置的, 所以只是在父进程给ignore掉了!! 子进程还是会收到信号的!! 
你可以试试上面那个程序就知道了!! 




 net_robber 回复于:2007-03-09 14:49:33

谢谢楼上回复

现在这个问题没有彻底解决,还剩下一个关键问题

进程A 用kill( 0, SIG )
自杀后,

为什么它的父进程也被干掉了???


 isnowran 回复于:2007-03-09 15:06:29

kill 0的意义是发送信号给它的进程组中所有进程,父进程若也在同样的进程组,当然也会接收到信号了


 net_robber 回复于:2007-03-09 15:15:57

但是为什么另外一个拥有同样PID的后台进程不被干掉

为什么拥有同样进程的BASH进程没有被干掉?????

这和Man里面解释的不一样啊


 net_robber 回复于:2007-03-09 15:20:17

如果现在我只想杀掉进程,以及他的全部子进程

我改怎么做??

每个进程在退出之前杀掉自己的子进程这种方法 不算


 net_robber 回复于:2007-03-09 15:31:12

可能只有利用SHELL比较快了


 net_robber 回复于:2007-03-09 15:32:57

ps awx -o "%p %P"|grep -w PID| awk '{ print $1  }'|xargs kill -9



 isnowran 回复于:2007-03-09 15:41:13

把你的程序简单修改了一下

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <signal.h>
#include <unistd.h>


void fun_kill( int sig )
{
        kill ( 0, SIGKILL );
}

int main( void )
{
    for( int i = 0; i < 3; i++ )
    {
        if( 0 == fork() )
        {
            break;
        }
    }

    if( getpid() == getpgid( 0 ) )
    {
        signal ( SIGTERM, SIG_IGN );
        sleep( 3 );
        kill( 0, SIGTERM );
    }
    else
    {
        while ( 1 )
        {
            printf ( "pid:%d ppid:%d\n", getpid(), getppid() );
            sleep ( 1 );
        }
    }

    printf( "game over\n" );
    return 0;
}



 isnowran 回复于:2007-03-09 15:46:16

引用:原帖由 net_robber 于 2007-3-9 15:15 发表
但是为什么另外一个拥有同样PID的后台进程不被干掉

为什么拥有同样进程的BASH进程没有被干掉?????

这和Man里面解释的不一样啊 


不太明白你说的"同样pid的后台进程"是什么意思,也不明白"拥有同样进程的BASH进程"是什么意思,请解释一下:)

l新的进程在shell环境生成后,一般都有setsid的操作,这样它们就不在同一个会话期,当然也不在同一个进程组了,所以shell不会受到kill 0的影响


 net_robber 回复于:2007-03-09 18:07:45

引用:原帖由 isnowran 于 2007-3-9 15:46 发表

不太明白你说的"同样pid的后台进程"是什么意思,也不明白"拥有同样进程的BASH进程"是什么意思,请解释一下:)

l新的进程在shell环境生成后,一般都有setsid的操作,这样它们就不在同一 ... 


大概就是你说的原因

还没有研究这么深入。


 net_robber 回复于:2007-03-09 18:13:22

getpid(), getppid()以前没有用过,学习一下再来讨论


 net_robber 回复于:2007-03-09 18:43:51

最终提供两套代码:
一套通过gid控制;
另一讨使用SHELL工作。


 net_robber 回复于:2007-03-09 18:45:01

这是通过gid控制




       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/types.h>
       #include <signal.h>
       #include <unistd.h>
       #include <string.h>
      
       void fun(int sig)
       {
              kill(0 , SIGKILL );
      }
     
      int main( void )
      {
              int pid = 0;
     
              if( pid = fork() )
              {
                      fflush( stdout );
                      sleep ( 5 );
                      printf ( "kill ( pid, SIG ); \n");
                      fflush( stdout );
                      kill ( pid, SIGUSR1 );
                      sleep ( 10 );
                      printf ( "the father is still alive!\n", pid );
                      fflush( stdout );
              }
              else
              {
                      setpgid(0,0);      //line 30
                      signal( SIGUSR1, fun );
                      if( pid = fork() )
                      {
                              int i = 10;
                              while ( i-- )
                              {
                                      fflush( stdout );
                                      sleep ( 1 );
                              }
                      }
                      else
                      {
                              int i = 10;
                              while ( i-- )
                              {
                                      printf ( "in grandsun , pid= %d\nin grandsun , ppid= %d\n", getpid(), getppid() );
                                      fflush( stdout );
                                      sleep ( 1 );
                              }
                      }
              }
     
              return 0;
      }




[ 本帖最后由 net_robber 于 2007-3-13 10:04 编辑 ]


 net_robber 回复于:2007-03-09 18:46:35

这是通过SHELL工作



       #include <stdio.h>
       #include <stdlib.h>
       #include <sys/types.h>
       #include <signal.h>
       #include <unistd.h>
       #include <string.h>
      
       void fun_kill( int sig )
       {
              printf( "process with PID %d got a signal!\n", getpid() );
              fflush( stdout );
              char *pre = "ps awx -o \"\%p \%P\"|grep -w ";
              char *post = " | awk \'{ print $1  }\'|xargs kill -9";
     
              char *command = malloc( 1024*sizeof (char) );
              char *c_pid = malloc( 8*sizeof (char) );
              memset ( command, 0, 1024*sizeof(char) );
              memset ( c_pid, 0, 8*sizeof(char) );
              char *a,*b;
              char c;
     
              //get PID string * NOTE: here the string is in a wrong order
              int len = 0;
              int tmp = getpid();
              for ( len = 0; tmp; tmp /= 10   )
              {
                      *( c_pid + len ) = (tmp%10)+'0';
                      len++;
              }
              printf ( "%s has %d char\n", c_pid,len );
              fflush( stdout );
     
              // deal the order
              a = c_pid;
              b = c_pid+len-1;
              printf ("c_pid = %d\n",c_pid);
              printf ("a = %d\n",a);
              printf ("b = %d\n",b);
              fflush( stdout );
     
     
              while ( a < b )
              {
                      c = *a;
                      *a =*b;
                      *b = c;
                      a += sizeof(char);
                      b -= sizeof(char);
              }
      /*
              int i = 0;
              while ( i<len )
              {
                      printf ("%c", *(c_pid+i) );
              }
      */
     
              printf ( "command1:%s\n", command );
              fflush( stdout );
     
     
              strcat ( command, pre );
              strcat ( command, c_pid );
              strcat ( command, post );
              printf ( "command2:%s\n", command );
              fflush( stdout );
     
           system( command );
     
      }
     
     
     
      int main( void )
      {
              int pid = 0;
     
              if( pid = fork() )
              {
      //              printf ( "in father, pid= %d\nin father, child pid = %d\n", getpid(), pid );
                      fflush( stdout );
                      sleep ( 5 );
                      printf ( "kill ( pid, SIG ); \n");
                      fflush( stdout );
                      kill ( pid, SIGUSR1 );
                      sleep ( 10 );
                      printf ( "the father is still alive!\n", pid );
                      fflush( stdout );
              }
              else
              {
                      signal ( SIGUSR1, fun_kill );
                      if( pid = fork() )
                      {
                              int i = 10;
                              while ( i-- )
                              {
      //                              printf ( "in child, pid= %d\nin child, ppid= %d\n", getpid(), getppid() );
                                      fflush( stdout );
                                     sleep ( 1 );
                              }
                      }
                     else
                     {
                             int i = 10;
                             while ( i-- )
                             {
     //                              printf ( "in grandsun , pid= %d\nin grandsun , ppid= %d\n", getpid(), getppid() );
                                     fflush( stdout );
                                     sleep ( 1 );
                             }
                     }
             }
    
             return 0;
     }
    





[ 本帖最后由 net_robber 于 2007-3-13 10:07 编辑 ]


 net_robber 回复于:2007-03-12 09:58:44

关于使用PGID的方法

请注意代码的第30行

这里需要说明:
setpgid函数后,本进程不再使用父进程的gid
其后,本进程产生的子进程使用本进程setpgid以后的gid


因此可以做到 SIGKILL后杀死本进程及本进程的所有子进程


 isnowran 回复于:2007-03-12 10:26:34

2个问题
1。生成进程后马上杀掉进程,这么做好像没什么意义,毕竟搂长的初衷是怎么杀掉所有子进程,此时应该父进程应该是已经生成一堆进程后并且没有保存子进程pid的情况

2。既然是指定pid单独发送信号,子进程再设置为组长好像没什么意义


 net_robber 回复于:2007-03-12 10:34:15

前几天,有个兄弟踢出了一个要杀掉所有子进程的问题

我当时作出了一些回答,但是并没有帮他完全解决问题。

所以,这里,我尝试把这个问题彻底解决

上面的代码只是一个DEMO。


谢谢关注,呵呵

只是不知道,当初提出这个问题的那位 兄弟(沙发),有没有看到这个帖子。

如果看到了,希望告知,我得方法能不能帮你解决问题


 告化甲头 回复于:2007-03-12 12:03:47

引用:原帖由 net_robber 于 2007-3-12 10:34 发表
前几天,有个兄弟踢出了一个要杀掉所有子进程的问题

我当时作出了一些回答,但是并没有帮他完全解决问题。

所以,这里,我尝试把这个问题彻底解决

上面的代码只是一个DEMO。


谢谢关注,呵呵

只是 ... 



isnowran提出的问题你还是没有解决嘛,并且,这个确实不能算是"杀死所有子进程"的方法

[ 本帖最后由 告化甲头 于 2007-3-12 12:06 编辑 ]


 net_robber 回复于:2007-03-12 13:23:20



不知道我是不是没有看懂你的意思

这里,我的两种方法都已经做到了杀掉全部子进程

请问你的意思是???


 告化甲头 回复于:2007-03-12 14:36:16

正常情况下,不可能如你所假设那样,生成子进程后马上就杀掉,这样没什么实际意义,大部分情况是,生成若干进程,工作一段时间后,父进程接收到要停止子进程的指令后才开始终止子进程的,比如

for(int i=0; i<3; i++)
{
    父进程生成子进程
    if(子进程)
        循环执行工作
}

父进程等待指令

试问在这种情况下,父进程怎么才能把上面生成的3个或N个子进程结束呢?


 net_robber 回复于:2007-03-12 14:58:21

父进程执行kill(0,SIGKILL)

前提需要父进程执行setpgid(,)

man 2 kill


 net_robber 回复于:2007-03-12 15:00:13

而且我说过了,上面只是一个DEMO

你当然可以在你需要的时候在执行杀掉子进程

在上面的DEMO中

等待执行kill的方法是等待信号SIGUSR1


 net_robber 回复于:2007-03-12 15:01:27

你不明白什么是DEMO么???


 net_robber 回复于:2007-03-12 15:05:47

任何问题的解决,都是有前提环境的假设的

你的问题已经改变了我的假设

如果回答你的问题就像回答“如何让一个死人学会放屁”一样,有点麻烦


 告化甲头 回复于:2007-03-12 15:27:21

哦,fork了2次,没看清楚,歹势


 converse 回复于:2007-03-12 22:52:08

好帖保留了。

但是几位以后帖代码的时候注意不要把行号给加进来了,不然别人copy编译会比较麻烦。


 net_robber 回复于:2007-03-13 10:08:13

已经修改了

去掉了行号

以后会注意的


 ttphc 回复于:2007-03-13 12:31:15

seem good




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=907131
转载请注明作者名及原文出处



收藏本页到: