这是可以使用我们的多个免费在线工作站(例如 Ubuntu Online、Fedora Online、Windows 在线模拟器或 MAC OS 在线模拟器)之一在 OnWorks 免费托管提供商中运行的命令 perlfork
程序:
您的姓名
perlfork - Perl 的 fork() 模拟
概要
注意:从 5.8.0 版本开始,fork() 模拟已经有了相当大的改进。
成熟了。但是,仍然存在一些已知的错误和差异
来自真正的 fork() 可能会影响你。请参阅“错误”和
下面的“注意事项和限制”部分。
Perl 提供了一个 叉子() 对应于同名 Unix 系统调用的关键字。
在大多数类 Unix 平台上 叉子() 系统调用可用,Perl 的 叉子()
只是简单地调用它。
在某些平台上,例如 Windows 叉子() 系统调用不可用,Perl可以
旨在模仿 叉子() 在口译员层面。虽然仿真旨在
尽可能与真实兼容 叉子() 在 Perl 程序的层面上,有
某些重要的差异源于以下事实:所有伪儿童
以这种方式创建的“进程”与操作系统位于同一个真实进程中
被关注到。
本文档提供了对功能和限制的总体概述
叉子() 仿真。请注意,此处讨论的问题不适用于平台
真正的 叉子() 可用并且 Perl 已配置为使用它。
商品描述
这个 叉子() 模拟是在 Perl 解释器级别实现的。这意味着什么
一般来说是运行 叉子() 实际上会克隆正在运行的解释器及其所有内容
状态,并在单独的线程中运行克隆的解释器,在新的线程中开始执行
线程就在该点之后 叉子() 被称为父级。我们将参考
将该子“进程”实现为伪进程的线程。
到调用的 Perl 程序 叉子(),这一切都是为了透明而设计的。这
父母从 叉子() 带有伪进程ID,随后可以在
任何流程操作功能;孩子从 叉子() 值为 0 到
表示它是子伪进程。
宠物行为研究 of other Perl的 功能 in 岔 伪进程
大多数 Perl 功能在伪进程中以自然的方式运行。
$$ 或 $PROCESS_ID
这个特殊变量已正确设置为伪进程 ID。可以用
识别特定会话中的伪进程。注意这个值是
如果在其他进程启动后启动任何伪进程,则将被回收
等待()-ed 继续。
%ENV 每个伪进程维护自己的虚拟环境。对 %ENV 的修改
影响虚拟环境,并且仅在该伪进程中可见,
以及从它启动的任何进程(或伪进程)中。
目录目录() 以及所有其他接受文件名的内置函数
每个伪进程都维护自己的当前目录的虚拟概念。
使用修改当前目录 目录目录() 仅在该范围内可见
伪进程,以及从它启动的任何进程(或伪进程)。全部
来自伪进程的文件和目录访问将正确映射虚拟进程
适当地将工作目录更改为实际工作目录。
等待() 和 等待pid()
等待() 和 等待pid() 可以传递一个伪进程 ID 返回 叉子()。 这些
调用将正确等待伪进程的终止并返回其
状态。
杀() “kill('KILL', ...)”可用于通过向伪进程传递 ID 来终止伪进程
由...返回 叉子()。伪进程的终止结果是不可预测的
除非在严重的情况下,否则不应使用它,因为操作
当线程运行时,系统可能无法保证进程资源的完整性
被终止。实现伪进程的进程可以被阻塞
并且 Perl 解释器挂起。请注意,在 a 上使用“kill('KILL', ...)”
伪过程() 通常可能会导致内存泄漏,因为线程
实现伪进程没有机会清理其资源。
“kill('TERM', ...)”也可以用于伪进程,但信号不会
当伪进程被系统调用阻止时传递,例如等待
用于连接套接字,或尝试从没有可用数据的套接字读取。
从 Perl 5.14 开始,父进程将不会等待子进程退出一次
他们已收到“kill('TERM', ...)”信号,以避免进程期间出现死锁
出口。您必须明确调用 等待pid() 确保孩子有时间
自己清理,但你也有责任让孩子不
也阻塞 I/O。
exec() 调用 exec() 在伪进程中实际上生成了所请求的可执行文件
一个单独的进程并等待其完成,然后以相同的退出退出
状态作为该过程。这意味着在
运行可执行文件将与早期 Perl 不同 叉子() 可能有
回。类似地,任何应用于 ID 的进程操作函数
由...返回 叉子() 将影响调用的等待伪进程 exec(),不
它在等待之后的真实进程 exec().
在规划婴儿食品行业的工艺要求时,安全性和可靠性是工艺设计中最重要的方面。 exec() 在伪进程内部调用,然后 DESTROY 方法和 END 块
外部进程返回后仍会被调用。
出口() 出口() 总是退出正在执行的伪进程,之后自动退出
等待()-ing 任何未完成的子伪进程。请注意,这意味着
除非所有正在运行的伪进程都已退出,否则整个进程不会退出
退出。有关打开文件句柄的一些限制,请参阅下文。
打开文件、目录和网络套接字的句柄
所有打开的手柄都是 复制()-ed 在伪进程中,以便关闭任何句柄
一个进程不会影响其他进程。请参阅下文了解一些限制。
更多相关资源 范围
在操作系统的眼中,通过以下方式创建的伪进程 叉子() 仿真是
只是同一进程中的线程。这意味着任何由
操作系统适用于所有伪进程。这包括任何
操作系统对打开文件、目录和套接字数量的限制
句柄、磁盘空间使用限制、内存大小限制、CPU 利用率限制等。
杀害 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 亲 工艺
如果父进程被终止(使用 Perl 的 杀() 内置的,或使用一些
外部手段)所有伪进程也被杀死,整个进程退出。
终身版 of 这些因素包括原料奶的可用性以及达到必要粉末质量水平所需的工艺。 亲 工艺 和 伪进程
在正常的事件过程中,父进程和每个伪进程都由
它将等待各自的伪子进程完成后再退出。这
意味着父级和由它创建的每个伪子级也是伪父级
仅在其伪子项退出后才会退出。
从 Perl 5.14 开始,家长不会 等待() 自动为任何已经被
用“kill('TERM', ...)”发出信号以避免子进程阻塞时出现死锁
I/O并且从不接收信号。
洞穴 AND 限制
BEGIN 块
这个 叉子() 从内部调用时,仿真将无法完全正确工作
BEGIN 块。分叉副本将运行 BEGIN 块的内容,但会
在 BEGIN 块之后不继续解析源流。例如,
考虑以下代码:
开始 {
分叉并退出; # 分叉子进程并退出父进程
打印“内部\n”;
}
打印“外部\n”;
这将打印:
内
而不是预期的:
内
外
这种限制源于克隆和克隆的基本技术困难。
在解析过程中重新启动 Perl 解析器使用的堆栈。
打开文件句柄
任何在该时间打开的文件句柄 叉子() 会 复制()-ed。因此,文件
可以在父级和子级中独立关闭,但要注意 复制()-ed
句柄仍将共享相同的查找指针。更改搜索位置
父母会在孩子身上改变它,反之亦然。人们可以通过打开来避免这种情况
需要在子级中单独查找指针的文件。
在某些操作系统上,特别是 Solaris 和 Unixware,从
子进程将刷新并关闭父进程中打开的文件句柄,从而
损坏文件句柄。在这些系统上,建议调用“_exit()”
反而。 “_exit()”在 Perl 中可通过“POSIX”模块使用。请
有关详细信息,请参阅系统的联机帮助页。
打开目录句柄
Perl 将从所有打开的目录句柄中完全读取,直到它们到达末尾
流的。然后它会 寻求目录() 回到原来的位置和所有
未来 读取目录() 请求将从缓存缓冲区中得到满足。这意味着
既不是父进程持有的目录句柄,也不是
子进程将看到对目录所做的任何更改 叉子()
呼叫。
需要注意的是 回滚目录() Windows 上也有类似的限制,不会强制
读取目录() 再次读取目录。仅新打开的目录
句柄将反映对目录的更改。
分叉管 打开() 尚未实现
“open(FOO, "|-")”和“open(BAR, "-|")”结构尚未实现。
通过创建管道,可以在新代码中轻松解决此限制
明确地。以下示例显示如何写入分叉子项:
# 模拟打开(FOO, "|-")
子管道到叉子 ($) {
我的 $parent = 转变;
管道我的$child,$parent,否则就死掉;
我的 $pid = fork();
die“fork() 失败:$!”除非定义了 $pid;
如果($pid){
关闭 $child;
}
其他{
关闭$parent;
open(STDIN, "<&= . fileno($child)) 或死掉;
}
$pid;
}
如果(pipe_to_fork('FOO')){
# 父级
打印 FOO“pipe_to_fork\n”;
关闭 FOO;
}
其他{
# 孩子
尽管 ( ) { 打印; }
出口(0);
}
这是孩子写的:
# 模拟打开(FOO, "-|")
子 pipeline_from_fork ($) {
我的 $parent = 转变;
管道 $parent,我的 $child 要么死;
我的 $pid = fork();
die“fork() 失败:$!”除非定义了 $pid;
如果($pid){
关闭 $child;
}
其他{
关闭$parent;
open(STDOUT, ">&=" . fileno($child)) 或死亡;
}
$pid;
}
如果(pipe_from_fork('BAR')){
# 父级
while () { 打印; }
关闭酒吧;
}
其他{
# 孩子
打印“pipe_from_fork\n”;
出口(0);
}
分叉管 打开() 未来将支持构建。
由 XSUB 维护的全局状态
维护自己的全局状态的外部子例程 (XSUB) 可能不起作用
正确。此类 XSUB 将需要维护锁以保护同时
从不同的伪进程访问全局数据,或维护它们的所有状态
在 Perl 符号表上,当 叉子() 叫做。 A
回调机制为扩展提供了克隆其状态的机会
将在不久的将来提供。
嵌入大型应用程序的解释器
这个 叉子() 仿真在执行时可能不会按预期运行
嵌入 Perl 解释器并调用可以评估的 Perl API 的应用程序
Perl 代码位。这是因为仿真只有知识
对 Perl 解释器自身的数据结构一无所知
包含应用程序的状态。例如,任何国家进行
应用程序自己的调用堆栈无法访问。
扩展的线程安全
由于 叉子() 模拟在多个线程中运行代码,扩展调用
非线程安全库在调用时可能无法可靠地工作 叉子()。正如 Perl 的
线程支持逐渐得到更广泛的采用,甚至在具有
本地人 叉子(),为了线程安全,预计会修复此类扩展。
可移植性 洞穴
在可移植 Perl 代码中,“kill(9, $child)”不得用于分叉进程。杀死一个
分叉进程是不安全的并且会产生不可预测的结果。看 ”杀()“, 多于。
使用 onworks.net 服务在线使用 perlfork