一、参考
二、信号
2.1 POSIX标准的信号
2.1.1 基本介绍
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
信号不同,它可以被进程捕获,解释或者忽略,这允许进程在合适的情况下执行良好的终止释放资源和保存状态,SIGINT
和SIGTERM
几乎相同
程序结束信号,与SIGKILL
不同的是该信号可以被阻塞和处理,通常用于要求程序自己正常退出,shell命令kill
不带参数,将产生这个信号,如果进程终止不了,才会尝试SIGKILL
SIGKILL: signal kill
kill
信号被发送到某个进程,使得该进程立即终止,和SIGTERM
和SIGINT
相反,这个信号不能被捕获或者忽略,并且接收过程在接收到这个信号时候不能执行任何清理,但是下面情况为例外:
(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
信号)
SIGTTIN
和 SIGTTOU
后台进程,试图从tty
读取或者写入时候,所有进程会收到SIGTTIN
, SIGTTOU
信号,通常,该信号仅由作业控制下的进程接收,守护进程没有控制终端,因此,不会接收到这些信号。
当后台作业要从用户终端读取数据时候,该作业中的所有进程会收到信号
SIGUSR1
和 SIGUSR2
留给用户使用,信号根据用户定义的条件发送
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 foobar
和wc -l
,标准输出通常被更改为管道的写入端,wc -l
可以将其标准输入更改为管道的读取端,用于读取cat foobar
程序输出的数据。
这种标准输入、标准输出(STDIN
和STDOUT
)到管道的变化是由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)