关闭

fork详解

46人阅读 评论(0) 收藏 举报
分类:

这个函数通过调用 fork(2) 系统调用,从一个进程中创建两个进程。如果它成功,该函数给 父进程返回新创建的子进程 ID,而给子进程返回0。如果系统没有足够的资源分配一个新的 进程,那么调用失败并返回undef。文件描述符(以及有时候还有在那些描述符上的锁)是共享的,而所有其他的东西都是拷贝的——或者至少看起来是那样的。
在早于 5.6 版本的 Perl 里,未冲刷的缓冲区在两个进程里都是没有冲刷的,这就意味着你需要在程序的早些时候在一个或多个文件句柄上设置 $| 以避免输出重复。
一个产生子进程然而有检查“cannot fork”错误的近乎没有毛病的方法是:

  1.    use Errno qw(EAGAIN);
  2.    FORK:{
  3.      if ($pid = fork) {
  4.        # 父进程在此
  5.        # 在 $pid 里可以看到子进程的进程id
  6.      }
  7.      elsif (defined $pid) {   # 如果定义了,$pid在这里是 0
  8.        # 子进程在此
  9.        # 你可以用 getppid 在这里获取父进程的pid
  10.      }
  11.      elsif ($! == EAGAIN) {
  12.        # EAGAIN 是认为可以恢复的 fork错误
  13.        sleep 5;
  14.        redo FORK;
  15.      }
  16.      else {
  17.        # 奇怪的 fork 错误
  18.        die "Can't fork: $!\n";
  19.      }
  20.    }

这些预防措施在那些做隐含的 fork(2) 的操作上是不必要的,比如 system,反勾号,或者把一个进程当作一个文件句柄打开,因为 Perl 在为你做 fork 的时候碰到临时的失败会自动重新 尝试 fork。要注意记得使用exit 结束子进程的代码,否则子进程会不小心地离开条件块并且 开始执行原来只是想让父进程执行的代码
如果你 fork 以后再也不等待你的子进程,那么你就会积累僵死进程(那些父进程还没等待它们 的退出进程)。在一些系统上,你可以通过设置$SIG{CHLD} 为“IGNORE”来避免这些;在 大多数系统上,你必须 wait 你的垂死的子进程。参阅 wait函数获做这些的例子,或则后参阅 第十六章的“信号”一节获取更多关于 SIGCHLD 的信息。
如果一个派生出来的子进程继承了系统文件描述符,象 STDIN 和 STDOUT 等,它们又和一个远程的管道或者套接字连接,那么你可能不得不在子进程里把他们重新打开到 /dev/null。这是因为即使父进程退出,子进程仍将带着这些文件句柄的拷贝继续生存。而远端服务器(比如说,一个 CGI 脚本或者一个从远程 shell发起的后台任务。)就会挂起,因为它仍然等待所有拷贝关闭。 重新把系统文件句柄打开成别的什么东西可以修补这个问题。
在大多数支持 fork(2) 的系统上,人们做了大量努力把它变得尽可能地高效(比如,数据页的写时拷贝(copy-on-write)技术),而它也成了过去几十年来多任务领域的典范。但是 fork函数可能并没有有效地(甚至可能是根本没有)在那些不象 Unix 的系统上实现。比如, Perl 5.6 甚至在 Microsoft系统上都模拟了一个合适的 fork,但是并不能保证可以达到很好 的性能。可能用 Win32::Process模块的时候,你的运气会好一些。


转自:http://www.perlcn.com/perlbc/perljj/1334.html
0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:8325次
    • 积分:500
    • 等级:
    • 排名:千里之外
    • 原创:40篇
    • 转载:11篇
    • 译文:0篇
    • 评论:0条
    文章分类