fork(2)
手册页说明如下:
子进程继承了父进程打开文件描述符的副本。子节点中的每个文件描述符引用相同的打开文件描述(请参阅open(2))作为父节点中的相应文件描述符。这意味着两个文件描述符共享打开文件状态标志,文件偏移量和信号驱动的I / O属性(参见fcntl(2)中F_SETOWN和F_SET-SIG的描述)。
Python文档提及
_exit()
通常只能在fork()
之后的子进程中使用。
当然,_exit
不会调用清理处理程序,问题是,如果你看一下这段代码:
newpid = os.fork()
if newpid == 0:
os.close(0)
else:
time.sleep(.25)
input()
尽管子进程关闭了stdin,但父进程仍接受来自stdin的输入。这很好,这里的代码反转了:
newpid = os.fork()
if newpid == 0:
input()
else:
time.sleep(.25)
os.close(0)
现在,情况正好相反,这次父进程关闭stdin而不是子进程。这会为子进程中的EOFError
调用提出input()
。
这看起来像[child]进程写入/修改父文件描述符时,它不会影响[parent]。也就是说,子进程获得更新的文件描述。
那么为什么调用_exit
作为Python Docs声明如果子进程执行的操作不影响父进程,则阻止调用清理处理程序?我们来看看_EXIT(2)
手册页:
函数
_exit() terminates the calling process "immediately". Any open file descriptors belonging to the process are closed; any children of the process are inherited by process 1, init, and the process's parent is sent a
SIGCHLD`信号。函数
_exit()
与exit(3)
类似,但不调用使用atexit(3)或on_exit(3)注册的任何函数。打开stdio(3)流不会刷新。另一方面,_exit()
会关闭打开的文件描述符,这可能会导致未知的延迟,等待挂起的输出完成。
fork()
手册页未提及子进程的清除处理程序是从父进程继承的。这对父母有何影响?换句话说,为什么不让孩子过程自我清理,为什么不呢?
答案 0 :(得分:1)
我假设你是在终端内的shell中运行它。
shell在新进程组中启动Python进程,并使用self.textInput.subscribe(function (newValue) {
if(newValue.match(/[a-z]/))
self.responseErrorMessage("Numbers only");
else
self.responseErrorMessage('');
});
将其设置为TTY上的前台进程组。
一旦父Python进程终止,shell将回收终端的控制权(它将自己设置为前台进程组)。 shell不知道Python的分叉子节点仍在运行。
当不属于前台进程组的进程尝试从终端读取时,它通常会收到tcsetpgrp()
信号。但是,在这种情况下,进程组已成为孤立状态,因为其领导者已终止,因此子进程在TTY上从SIGTTIN
收到EIO
错误。 Python将其视为read()
。