gunicorn进程管理源码解析

一、参考

github gunicorn

wiki signal

What-is-SIGCHLD-in-Linux

二、信号

2.1 POSIX标准的信号

2.1.1 基本介绍

image.png

SIGCHID: signal child

当子进程终止、被中断或者被中断后恢复,SIGCHID信号被发送到父进程,该信号的常见用法是:指示操作系统在子进程终止后,清理子进程使用的资源

SIGHUB: signal hangup

当控制终端被关闭时候,SIGHUB信号被发送到父进程,它最初设计用于通知串行线路中断(挂断)的过程,在现代操作系统中,SIGHUB信号通常意味着控制伪终端或者虚拟终端已经被关闭,许多守护进程在接到该信号后,将会重新加载它们的配置文件并且重新打开它们的日志文件,通常不会在收到信号后,退出。使用NOHUP命令会忽略该信号。

注:例如,django web开发环境,直接使用nohup 命令开启服务,关闭终端不会影响到web server服务

SIGQUIT: signal quit

QUIT字符(通常是Ctrl-来控制)触发,进程在收到SIGQUIT信号退出时候会产生core文件,在这个意义上类似于一个程序错误信号

SIGINT: signal interrupt
当用户希望中断进程时候,在控制终端按下INTE字符(通常是Ctrl+C)后,控制终端将发送信号SIGINT到其他进程

SIGTERM: signal termination

terminal信号被发送到进程以请求其终止,与SIGKILL信号不同,它可以被进程捕获,解释或者忽略,这允许进程在合适的情况下执行良好的终止释放资源和保存状态,SIGINTSIGTERM几乎相同
程序结束信号,与SIGKILL不同的是该信号可以被阻塞和处理,通常用于要求程序自己正常退出,shell命令kill不带参数,将产生这个信号,如果进程终止不了,才会尝试SIGKILL

SIGKILL: signal kill

kill信号被发送到某个进程,使得该进程立即终止,和SIGTERMSIGINT相反,这个信号不能被捕获或者忽略,并且接收过程在接收到这个信号时候不能执行任何清理,但是下面情况为例外:
(1)僵尸进程(zombie)进程不能被杀死,因为它们已经死了,僵尸进程在等待其父进程捕获处理;
(2)处于阻塞状态的进程在再次被唤醒之前不能被杀死;
(3)init进程是特殊进程,它不接收不想处理的信号,所以它可以不接收kill信号,Linux中的ptraced init进程是例外;
(4)不间断的睡眠进程可能不会终止(释放资源),即使接收到SIGKILL,这是少数的需要重新启动操作系统,用于解决临时软件问题的情况之一。

在大多数操作系统关机过程中,SIGKILL用于终止进程的最后手段,如果SIGTERM不能主动退出。
为了更快的关机,Mac OS X 10.6(雪豹,snow leopard)把SIGKILL信号发送到被标记为clean的应用程序,从而加快这些应用程序的关闭过程,而且估计不会带来任何不良的影响。

shell命令kill -9对应着SIGKILL信号,该命令可能带有不良影响,因为该命令不允许进程保存未保存的数据,通常使用更加安全的shell命令(kill 不带参数,即SIGTERM信号)

SIGTTINSIGTTOU
后台进程,试图从tty读取或者写入时候,所有进程会收到SIGTTIN, SIGTTOU信号,通常,该信号仅由作业控制下的进程接收,守护进程没有控制终端,因此,不会接收到这些信号。
当后台作业要从用户终端读取数据时候,该作业中的所有进程会收到信号

SIGUSR1SIGUSR2
留给用户使用,信号根据用户定义的条件发送

SIGWINCH: signal window change
当控制终端窗口大小变化时候,SIGWINCH信号发送到进程

2.1.2 信号总结

终端Ctrl-产生信号SIGQUIT
终端Ctrl-C产生信号SIGINT
shell命令kill不带参数产生信号SIGTERM
shell命令kill -9产生信号SIGKILL

2.2 管道

管道(pipe),一个管道基本上是内核中的一块内存,一个由某些进程读写的缓冲区,使用管道的优点是它有两个相关联的文件描述符,因此在两个进程之间共享数据就像是读写文件一样简单。

import os
rfd, wfd = os.pipe()
# rfd, wfd = (3, 4) 文件描述符

基本上管道所做的是保留一个内存块,并返回两个文件描述符,这些描述符可以用于从该内存块中写入数据和读取数据。因此,两个进程间通信,进程A可以通过wfd写入数据,进程B可以通过rfd读取数据。

例如:
cat foobar | wc -l
这将运行2个进程cat foobarwc -l,标准输出通常被更改为管道的写入端,wc -l可以将其标准输入更改为管道的读取端,用于读取cat foobar程序输出的数据。

这种标准输入、标准输出(STDINSTDOUT)到管道的变化是由shell进程控制的,

STDIN  => cat => WRITE\_END==READ\_END => wc => STDOUT

管道的基本原理和日常生活中的水管一样,把东西从一个地方转移到另外一个地方。

还有一些要注意的,
读会阻塞在空管道上,写会阻塞在满的管道上,这是因为读空管道,没有数据刻度,写满管道,没有内存写入空间,因此它们会等待数据的读取或者等待内存的空闲,可以使用O_NONBLOCK标志标识管道不会阻塞

import os  
import sys  
  
  
r, w = os.pipe()  
process_id = os.fork()  
  
if process_id:  
    # Close write fd because parent not going to write  
    os.close(w)  
    r = os.fdopen(r)  
    # Read from pipe  
    msg = r.read()  
    print "msg =", msg  
    sys.exit(0)  
else:  
    # This is the child process  
    # Close read end cause child not going to read from pipe  
    os.close(r) 
    w = os.fdopen(w, 'w')  
    # Write to pipe  
    w.write("msg written by child...")  
    w.close()  
    sys.exit(0)

三、源码解析

你可能感兴趣的:(sina-app-engine,linux)