假設你的perl
有semop
和 的朋友,你可以使用System V信號量在孩子之間進行同步。下面的 爲一個工作示例程序。
我們從平常的事情開始。代碼使用內置的 IPC::SysV和 IPC::Semaphore模塊,而不是直接調用低級別信號量操作。
#! /usr/bin/env perl
use strict;
use warnings;
use IPC::Semaphore;
use IPC::SysV qw/ IPC_PRIVATE S_IRUSR S_IWUSR IPC_CREAT /;
該程序將子進程分成兩個階段。兒童在 第一階段運行完成,執行他們的處理沒有 同步問題。我們可以有任意許多這些。
我們有一個第二階段的過程,但它執行畢竟 第一階段的孩子已經完成。
下面是簡單的佔位符實現。
# how many other children the last child must wait for
my $FIRST_STAGE_CHILDREN = 2;
sub first_stage {
my($id) = @_;
print "[$$] hello from child $id\n";
sleep rand 10;
print "[$$] child $id done\n";
}
sub second_stage {
print "[$$] hello from second-stage child!\n";
}
爲了實現第一和第二階段之間的同步,所述 程序創建一組信號量的,其大小等於 第一級的兒童的數量。當第一階段孩子完成時,程序 釋放與該孩子相對應的特定信號量。
my $sem = IPC::Semaphore->new(
IPC_PRIVATE, $FIRST_STAGE_CHILDREN,
S_IRUSR | S_IWUSR | IPC_CREAT)
or die "$0: failed to create semaphore: $!";
稍後我們會看到,第二階段的孩子通過 試圖減小他們的信號燈等待他的弟兄們。當第二階段孩子嘗試這些減量時,通過將值設爲零開始, ,操作系統將讓孩子睡覺,因爲。只有在所有第一階段的孩子退出並釋放信號後 纔會阻止 第二階段的孩子。
# start in blocked state
$sem->setall((0) x $FIRST_STAGE_CHILDREN);
首先我們fork
第一階段的孩子。在這種設計中,父母 過程儘可能多地記賬。這使first_stage
和second_stage
的定義 保持簡單。另外,如果第一階段的孩子以某種方式退出而沒有釋放其信號量,則第二階段 不會有跑步的希望。
my %kids;
foreach my $id (0 .. $FIRST_STAGE_CHILDREN - 1) {
my $pid = fork;
die "$0: fork: $!" unless defined $pid;
if ($pid) {
++$kids{$pid};
}
else {
first_stage $id;
$sem->op($id, 1, 0); # release
exit 0;
}
}
現在我們分叉第二階段的孩子。重要提示:儘管代碼 對多個信號量執行操作,但原子上會發生, ,也就是說,它可以適用於所有這些信號,也可以不適用於它們。在沒有 可觀察到的狀態下,它會顯示第二階段能夠搶佔第一階段信號量的任何少於全部的 。這是一個重要的 屬性。在更復雜的系統中,隨意發佈和釋放將導致死鎖。
my $pid = fork;
die "$0: fork: $!" unless defined $pid;
if ($pid) {
++$kids{$pid};
}
else {
# block waiting on all first-stage children
my @op = map +($_, -1, 0), 0 .. $FIRST_STAGE_CHILDREN - 1;
$sem->op(@op);
second_stage;
exit 0;
}
最後,父進程等待所有孩子完成。
do {
$pid = waitpid -1, 0;
print "[$$] reaped $pid\n";
warn "$0: unknown child $pid" unless delete $kids{$pid};
} while $pid > 0 && keys %kids;
樣本輸出如下。觀看現場可以看到停頓更有趣。
[18389] hello from child 0
[18390] hello from child 1
[18390] child 1 done
[18388] reaped 18390
[18389] child 0 done
[18391] hello from second-stage child!
[18388] reaped 18389
[18388] reaped 18391
你可以讓父母等待child1在產卵之前完成child2嗎?是否有要求在child1完成之前產生child2? – Joel
我之所以需要等待,是因爲產卵後的父母所做的事情在時間上有些敏感。 –