从子堆栈中删除Perl模块

时间:2012-02-05 00:49:55

标签: perl memory fork

我有一个守护进程,它加载DBI(DBD :: mysql)然后分叉子进程。我想阻止DBI模块在分叉子进程中的内存中。

这样的事情:

#!/usr/bin/perl

use DBI;
my $dbh = DBI->connect(db_info);

my $pid = fork();
if($pid){

# The forked process here should not have DBI loaded

}

感谢您的帮助!

4 个答案:

答案 0 :(得分:4)

除非你把叉子放在后面,否则你不能轻易做到这一点。但要做到这一点,你必须不使用use。这样做:

my $pid = fork();
if ($pid) {
     # child
} else {
     require DBI;
     import DBI;
}

这应该阻止DBI模块加载到fork之后。 use例程基本上执行require / import但在BEGIN {}块内,这就是为什么你不能使用它。

答案 1 :(得分:4)

加载模块就像脚本一样执行它。模块和Perl脚本之间绝对没有区别。要卸载模块,需要撤消运行它的效果。这不能用机械方式完成,手动做是不可行的。

最简单的解决方案是让孩子exec。它甚至可能是你已经运行的脚本。

exec($^X, $0, '--child', @args)

可以通过将子节点绑定到子节点的fd 0(stdin)和fd 1(stdout)来为子节点提供访问权限。

答案 2 :(得分:1)

如果您正在运行现代Linux系统,那么分叉就是COW(写入时复制)。这意味着父节点中的页面只有在父节点或子节点修改后才会复制到子节点的地址空间。因此,DBI模块不在分叉子进程的内存中。

Perl 5没有任何从内存中卸载模块的方法。如果由于某种原因你真的需要孩子们拥有与父母不同的代码,你最好将代码从主代码中分离出来作为自己的脚本,然后在fork之后使用exec来运行子脚本。这将比正常分叉慢,因为它必须编译子代码,所以如果你分叉很多,最好有两个脚本通过套接字相互通信并且具有pre-fork的“子”脚本。 / p>

答案 3 :(得分:1)

现在知道你想用它做什么,因为没有一个很好的方法来卸载我的Perl模块,这是一个很好的解决方案,可以编写一个独立于应用服务器的认证服务器。如果IP具有权限,则应用程序服务器会询问身份验证服务器。这样他们仍然处于完全独立的过程中。这可能还有安全优势,您的应用程序代码无法访问您的身份验证数据库。

由于任何给定的应用程序可能会扩展到需要自己的SQL数据库,因此这个练习可能是徒劳的,但是你的电话。

这是一堆额外的工作,维护和复杂性。如果它导致你真正的记忆问题,这只是值得,而不仅仅是因为它是你的错误。记住,RAM非常便宜。开发人员的时间非常昂贵。