当从父级分叉的子进程死亡时,它仍然存在一定程度并且处于僵尸状态,直到从wait()调用中获取。
是否可以分离这个父子关系并让孩子自动获得收入?也许可以将孩子从初学者那里孤儿或其他东西?
可能的用例:在一个长期存在的程序中创建大量的“即发即弃”流程,而不是"持有"更多的僵尸PID无法通过操作系统回收。
答案 0 :(得分:5)
每the POSIX _exit() documentation:
如果调用进程的父进程已设置了它
SA_NOCLDWAIT
标记或已将SIGCHLD
信号的操作设置为SIG_IGN
:
过程'状态信息(见状态信息),如果有的话,应该被丢弃。
呼叫过程的生命周期应立即结束。如果设置了
SA_NOCLDWAIT
,则是SIGCHLD
是实现定义的 信号被发送到父进程。如果调用进程的父进程中的某个线程在
wait()
,waitpid()
或waitid()
中被阻止,并且父进程已 在这组等待的孩子中没有剩余的子进程wait()
,waitid()
或waitpid()
功能将失败并设置errno
到[ECHILD
]。否则:
应生成状态信息(参见状态信息)。
调用流程应转换为僵尸流程。其状态信息应提供给父进程 直到过程'终身结束。
...
简而言之,为了防止子进程成为僵尸进程,最简单的方法是调用sigignore( SIGCHLD );
<强>更新强>
这确实会影响等待任何子进程的能力,这可能是不可取的。 setsid()
library function允许进程与其父进程取消关联:
pid_t child = fork();
if ( ( pid_t ) 0 == child )
{
int rc = setsid();
rc = execv(...);
}
else ...
解除关联的子进程不会创建僵尸,也不会将SIGCHLD
发送到我安装的Solaris 11.2实例上的父进程。
这是&#34;“即发即忘”的缩写守护程序。子进程,只执行必要的操作以防止创建僵尸或将SIGCHLD
发送到父进程。有关更全面的守护程序,请参阅Linux daemonize
答案 1 :(得分:1)
忽略SIGCHLD
或为SIGCHLD
安装一个sighandler并启用SA_NOCLDWAIT
标志,可以防止所有子级变成僵尸(/可以wait
使用)。
要为一个孩子做这件事,您可以使用不带clone()
标志的Linux的SIGCHLD
,也可以加倍fork
(或vfork
,如果您知道如何安全地这样做)。然后,孩子可以立即_exit(0)
wait
并由其父母init
抚养,孙子可以继续从事实际工作(就像您所说的ps
一样)。
(双叉的轻微扩展将是完全妖魔化,子代或孙子也会调用setid来创建新会话,新进程组并与控制终端分离。Setsid单独不会阻止孩子成为僵尸,只会在默认设置中将ps
中的僵尸隐藏在window.onload = function() {
var chart = new CanvasJS.Chart("chartContainer",
{
toolTip: { borderThickness: 3 },
data: [
{
indexLabelFontColor: 'white',
indexLabel: "{label} ",
indexLabelPlacement: "inside",
toolTipContent: "<b>{label}</b><br>{text}<br/>",
type: "pie",
cursor:"pointer",
dataPoints: [
{ label: "Collaborate", y: 16, link:"http://google.com/", text:'gg' },
{ label: "Discuss", y: 16, link:"http://bing.com/", text:'gg'},
{ label: "Practice", y: 16, link:"http://search.yahoo.com/", text:'gg' },
{ label: "Investigate", y: 16, link:"http://www.duckduckgo.com/", text:'gg' },
{ label: "Acquire Knowledge", y: 16, link:"http://www.duckduckgo.com/", text:'gg' },
{ label: "Produce", y: 16, link: "http://www.dogpile.com/", text:'gg' }
]
}
]
});
chart.options.data[0].click = function(e){
var dataSeries = e.dataSeries;
var dataPoint = e.dataPoint;
var dataPointIndex = e.dataPointIndex;
if(!dataPoint.exploded)
window.open(dataPoint.link,'_blank');
for(var i = 0; i < dataSeries.dataPoints.length; i++){
if(i === dataPointIndex){
continue;
}
dataSeries.dataPoints[i].exploded = false;
}
};
chart.render();
}
中,其中traffic_id|date|start_time|session_id|page|platform|page_views|revenue|segment_id|customer_id
303|1/1/2017|05:23:33|123457080|homepage|mobile|581|37.40|1|310559
仅显示当前终端控制会话中的进程。)
答案 2 :(得分:-1)
从Python 3.2开始,您可以使用subprocess.Popen()并传递start_new_session = True来完成此操作。
文档状态:
如果start_new_session为true,则将在子进程执行之前在子进程中进行setsid()系统调用。 (仅适用于POSIX)
https://docs.python.org/3/library/subprocess.html#subprocess.Popen
请注意,如后续评论中所述,这不允许一个人“在孩子的一生中的任意阶段从父母那里做这件事”。