繁体   English   中英

在Linux上的Perl中分叉新进程

[英]forking a new process in perl on linux

我想从cgi调用派生一个后台进程。 这样,httpd调用立即返回,其余内容继续运行

这曾经一直起作用,直到我们迁移到新机器上

............
## Close the http connection so that the remote client returns
close STDOUT;
close STDERR;
POSIX::setsid();
fork() && exit;
do_job();
.........

现在在新机器上,相同的代码将永远不会执行do_job()Perl,httpd版本是相同的(有一个小的内核升级)

现在我将代码更改为

..........
open(STDOUT,">/dev/null");
open(STDERR,">/dev/null");
POSIX::setsid();
fork() && exit;
do_job();
.........

这有效,但我不确定为什么

我不太确定为什么第一个代码会起作用。 但是您应该始终将setsid放在fork()之后。 执行完此操作后,请告诉我是否无效。

每个过程组都在一个唯一的会话中。 (创建进程后,它将成为其父级会话的成员。)按照惯例,会话的会话ID等于会话的第一个成员(称为会话领导者)的进程ID。 进程使用系统调用getsid()查找其会话的ID。

创建了一个新会话

pid = setsid();

仅当当前流程不是流程组负责人时才允许这样做。

让我解释一下原因。 假设您是流程组负责人或会话负责人,则必须了解流程组和会话ID是根据创建它们的流程的流程ID初始化的(然后引导它们,例如,对于会话负责人pid == sid和流程)组长pid == pgid)。 此外,进程组不能在会话之间移动。

这意味着,如果您是流程组组长,并且允许创建新会话,则sid和pgid将被设置为您的pid,而旧流程组中的其他进程则处于怪异状态:它们的流程组组长突然在不同的会话中,那么他们本人可能就在。 而且这是不允许的,因此内核返回了EPERM。

现在,如果您既不是会话组也不是进程组组长,则使用fork(),因此将sid和pgid设置为pid是安全的,因为该组中没有其他进程。

以下链接可能会有所帮助:

会议和过程组

Linux内核:过程

我建议您使用处理此类工作的外部队列。 您可以使用某些CPAN模块来获得此功能,例如Queue :: DBI或其他模块(例如Gearman)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM