我正在运行的Linux系统上的fork(2)手册页面如下所示:
子节点继承父级打开的文件描述符集的副本。子文件描述符中的每个文件描述符与父文件描述符中的相应文件描述符引用相同的打开文件描述(参见open(2))。这意味着两个文件描述符共享打开的文件状态标志、文件偏移量和信号驱动的I/O属性(请参阅fcntl(2)中对F_SETOWN和F_SETOWN的描述)。
和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)现在,正好相反,这一次关闭父进程的不是子进程。这将引发子进程中的EOFError调用input()。
这看起来就像子进程写入/修改父进程的文件描述符时,它不会影响父进程。也就是说,子进程获得较新的文件描述。
那么,如果子进程执行的操作不影响父进程,为什么调用_exit作为Python状态来阻止调用清理处理程序?让我们看一看_EXIT(2)手册页:
函数SIGCHLD
signal. The function_exit()is likeexit(3), but does not call any functions registered with atexit(3) or on\_exit(3). Open stdio(3) streams are not flushed. On the other hand,_exit()`关闭打开的文件描述符,这可能导致未知的延迟,等待挂起的输出完成。
fork()手册页面没有提到子进程的清理处理程序是从父进程继承的。这对父母有什么影响?换句话说,为什么不让孩子们自己清理一下,为什么不呢?
发布于 2017-07-06 13:40:35
我假设你是从终端的外壳中运行这个的。
shell在一个新的进程组中启动process,并使用tcsetpgrp()将其设置为TTY上的前台进程组。
一旦父Python进程终止,shell将收回终端的控制(它将自己设置为前台进程组)。shell不知道Python中的分叉子程序仍在运行。
当不属于前景进程组的进程试图从终端读取时,它通常接收SIGTTIN信号。但是,在这种情况下,进程组已经成为孤立的,因为它的领导终止了,因此子进程从TTY上的EIO从read()获得一个错误。Python将此视为EOFError。
https://stackoverflow.com/questions/44949988
复制相似问题