让进程安全地退出

终止一个进程有很多方法(咱只说linux环境):前台运行的进程,如果没有提供退出功能,我们通常会Ctrl+C进行终止;后台或守护进程,如果也没有提供退出命令啥的,咱通常会kill掉;此外还有类似关机或重启之类的特殊情况,也会导致进程终止。

无论哪种方法,最终都是通过向进程传递信号量的方式进行终止。只是不同的方式发送的信号也不同:比如Ctrl+C发送的是SIGINT,kill和killall发送的是SIGTERM,kill -9发送的是SIGKILL,等等。

有些信号可以在程序中捕获,针对进行特殊处理;而有些则手动捕获不了或不能忽略,只能服从命令。

对于那些可以捕获到的终止类信号(如SIGTERM、SIGHUP、SIGINT等),就如同家长向正在玩仙剑的孩子说道:“玩儿一下午了,别玩了。”

如果碰到顽皮的,那么很可能就当作耳边风了——捕获到信号后选择不终止进程;

如果孩子还算听话,那么就赶紧把游戏存个档退出了——捕获到信号后做好收尾工作,然后终止进程(安全退出,推荐);

有的则图省事直接退出——不捕获信号或不做特殊处理,直接终止进程(大部分人都这么做,不推荐);

如果碰到的是个严厉的家长,二话不说直接上前把游戏关掉,这下孩子傻眼了“我擦,还没存档!!!”——接收到了不可被忽略的终止信号

另外还有一点需要注意,针对关机和重启的情况,是由操作系统按PID正序逐个发送SIGTERM,通知大家“做好准备,要关机了”,随后(n秒后)会下最后通谍——SIGKILL。对于子进程来说,父进程由于PID小,会先收到SIGTERM,收到后会立即向子进程发SIGKILL结束子进程。这样很可能会造成子进程接收不到操作系统发的SIGTERM,还未进行收尾工作就被终止。所以,还是尽量在主进程做收尾工作,或者主进程收到SIGTERM后主动向子进程发送SIGTERM(我是这么想的,未验证 -.-)。

---------------------------------------------------我是分割线------------------------------------------------------------

附录:

网上的一段示例代码(Python)

#!/usr/bin/env python
import time
import signal
import sys

NEEDEXIT=False
def SignalHandler(sig, id):
    global NEEDEXIT
    if sig == signal.SIGUSR1:
        print 'received signal USR1'
    elif sig == signal.SIGHUP:
        print 'received signal HUP'
    elif sig == signal.SIGTERM:
        print 'received SIGTERM, shutting down'
        NEEDEXIT = True

signal.signal(signal.SIGUSR1, SignalHandler)
signal.signal(signal.SIGHUP, SignalHandler)
signal.signal(signal.SIGTERM, SignalHandler)

while 1:
    if NEEDEXIT:
        sys.exit()
    time.sleep(1)


参考资料:

http://hi.baidu.com/wuhy1213/blog/item/13f040066843225b0308818b.html

http://bbs.chinaunix.net/thread-99933-1-1.html

http://hi.baidu.com/syqust/blog/item/cb1fae01e8aa641a1c958321.html

http://bbs.chinaunix.net/thread-2197309-1-1.html

你可能感兴趣的:(让进程安全地退出)