LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2215|回复: 5

kill掉父进程,子进程还在运行?(谢谢!)

[复制链接]
发表于 2010-7-8 16:43:51 | 显示全部楼层 |阅读模式
书上说kill掉父进程,其下的子进程也跟着消亡:
例如:
[root@qht2 ~]# ps -ef | grep httpd
root      3799     1  0 10:41 pts/0    00:00:00 /usr/sbin/nss_pcache off /etc/httpd/alias
root      3803     1  3 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3807  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3808  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3809  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3810  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3811  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3812  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3813  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
apache    3814  3803  0 10:41 ?        00:00:00 /usr/sbin/httpd
root      3816  3749  0 10:42 pts/0    00:00:00 grep httpd
[root@qht2 ~]# kill 3803
[root@qht2 ~]# ps -ef | grep httpd
root      3820  3749  0 10:42 pts/0    00:00:00 grep httpd
显然kill掉父进程,子进程也消亡了!

这是正确的!

但为什么下面的情况,就不符合上面的说法!
我写了两个脚本a.sh 和b.sh, 在a.sh中调用b.sh,运行后显然有两个进程,而且a.sh为b.sh的父进程,然后我再另外一个terminal中kill 掉a.sh进程,但b.sh过寄给init进程,而不会终止!
我的例子如下:
[root@qht2 ~]# cat a.sh
#!/bin/sh
echo "A Begin"
./b.sh
echo "A End"
[root@qht2 ~]# cat b.sh
#!/bin/sh
echo "B Begin"

sleep 180
mkdir abcdef
echo "B End"
[root@qht2 ~]# ./a.sh
A Begin
B Begin
在这里等待(因为b.sh中有sleep 180)


打开另一个terminal,查看进程
[root@qht2 ~]# ps -ef | grep sh
。。。。。。
root      3984  3749  0 11:05 pts/0    00:00:00 /bin/sh ./a.sh
root      3985  3984  0 11:05 pts/0    00:00:00 /bin/sh ./b.sh ##显然b.sh是a.sh的子进程
root      3990  3838  0 11:05 pts/1    00:00:00 grep sh
[root@qht2 ~]# kill 3984
[root@qht2 ~]# ps -ef | grep sh
。。。。。。
root      3985     1  0 11:05 pts/0    00:00:00 /bin/sh ./b.sh
root      3992  3838  2 11:06 pts/1    00:00:00 grep sh

第一ternimal中的显示如下:
[root@qht2 ~]# ./a.sh
A Begin
B Begin
Terminated
但b.sh还是会运行(因为生成了abcdef目录)!
那位老大解释下两者的区别、原因
谢谢!
发表于 2010-7-8 22:15:51 | 显示全部楼层
父进程退出,子进程被init领养,继续运行,这才是正常的吧

而前一个,从名字看明显是一个守护进程,id=3803的是会话首进程,也是进程组的组长,KILL掉它,会导致SIGHUP发送给该进程组的每一个进程(就是所有父进程为3803的那些),默认情况下,SIGHUP会终止进程,所以全没了.

详细情况,参考APUE2的第9,第10章,13章写的很明白.
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-7-9 09:00:51 | 显示全部楼层
首先表示对老兄表示感谢!
你的意思是守护进程和普通进程在kill时是有区别的?
只有守护进程是父进程被kill,子进程就自动消亡?
普通进程的父进程被kill掉,被init进程领养?
你说的apue2是啥东东?
谢谢
回复 支持 反对

使用道具 举报

发表于 2010-7-9 10:35:39 | 显示全部楼层
Post by qingheliu;2102167
首先表示对老兄表示感谢!
你的意思是守护进程和普通进程在kill时是有区别的?
只有守护进程是父进程被kill,子进程就自动消亡?
普通进程的父进程被kill掉,被init进程领养?
你说的apue2是啥东东?
谢谢

其实基本一样的,但小有区别.
首先要清楚会话,进程组,控制终端这几个概念.
所有进程都是属于一个进程组的,而进程组又属于一个会话.
普通的进程所属的会话有控制终端,守护进程所属会话没有控制终端.

普通会话的首进程,同时也是建立与控制终端联系的进程,在它被KILL掉时,会向前台进程组发送SIGHUP信号.默认情况下,接收到SIGHUP的进程会被终止.此时后台进程组不受影响.

守护进程的会话,因为没有控制终端,所以就没有前后台进程组之分,会话首进程同时也是进程组组长.它被KILL掉会向该组每个进程发送SIGHUP,导致组中进程被中止.

楼主的第二个试验,一个脚本掉另一个脚本的行为,创建了一个新的进程组,脚本A是进程组组长,但却不是所在会话的首进程或控制进程,所以它被KILL掉,不影响同组的进程(脚本B),此时init进程会自动领养脚本B所在进程,并在它运行到结束时回收它所占用的资源.

楼主可以用ps -eo pid,ppid,pgrp,session,comm跑一下.
对于第一种情况,就是守护进程,应该会发现那一堆进程的session(会话ID)和pgrp(组ID)都一样且是相同的,而且正好等于子进程的ppid,同时也是你KILL掉那个进程的pid.这样可以证实你KILL掉的是会话首进程.

对于第二种情况,你会发现,进程A和B,session和pgrp是一样的,但两者却并不相同,session的值虽无法确定,但pgrp却应该正好是进程A的pid,这说明了进程A是组长但却不是会话首进程,所以KILL掉它不会导致子进程被结束.
回复 支持 反对

使用道具 举报

发表于 2010-7-9 10:39:23 | 显示全部楼层
Post by qingheliu;2102167
首先表示对老兄表示感谢!
你的意思是守护进程和普通进程在kill时是有区别的?
只有守护进程是父进程被kill,子进程就自动消亡?
普通进程的父进程被kill掉,被init进程领养?
你说的apue2是啥东东?
谢谢


另,APUE2中文译名是<UNIX环境高级编程>(第二版),非常好的一本书,第9章(进程关系),第10章(信号),第13章(守护进程)对这个问题讲的非常清楚
回复 支持 反对

使用道具 举报

 楼主| 发表于 2010-7-9 13:55:15 | 显示全部楼层
明白了!
兄弟高手也!
对进程理解的很透彻!
多谢!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表