【问题标题】:shared memory and fork共享内存和分叉
【发布时间】:2014-06-21 10:49:20
【问题描述】:

我正在使用 fork 创建 9 个进程,我希望它运行:4 次打印“a selected.”,3 次打印“b selected”,2 次打印“c selected”。为此,我需要为每个运行案例减少一个计数器,并且我需要使用共享内存,但不知道如何,你能帮忙吗?

#!/usr/intel/bin/perl5.14.1

my $all_running = 9;            #2+3+4
my @times_to_run = (4, 3, 2);
my (@children, @non_empty_cells);

# make an array which will save the indexes of cells in @times_to_run which aren't empty

for (my $i = 0; $i < scalar(@times_to_run); $i++) {
  if ($times_to_run[$i] != 0) {
    push(@non_empty_cells, $i);
  }
}

while ($all_running > 0) {      #run 5 times

  my $pid = fork();

  if (!defined($pid)) {
    print("Fork Failed\n");
  }
  elsif ($pid > 0) {

    #parent
    push(@children, $pid);
    sleep(0.5);
  }
  else {  # child

    # pick a non-empty cell

    my $random_ = int(rand(@non_empty_cells));

    if ($non_empty_cells[$random_] == 0) {
      print "a chosen\n";
      $times_to_run[0]--;
      print "now $times_to_run[0]\n";

    }
    elsif ($non_empty_cells[$random_] == 1) {
      print "b chosen \n";
      $times_to_run[1]--;
      print "now $times_to_run[1]\n";

    }
    else {
      print "c chosen\n";
      $times_to_run[2]--;
      print "now $times_to_run[2]\n";

    }

    # update non empty-cells array

    @non_empty_cells = ();

    for (my $i = 0; $i < scalar(@times_to_run); $i++) {
      if ($times_to_run[$i] != 0) {
        push(@non_empty_cells, $i);
      }
    }

  # print "now empty cells is : ".scalar(@non_empty_cells)."\n\n";
    exit 0;
  }

  $all_running--;
}

foreach (@children) {
  my $tmp = waitpid($_, 0);
}

【问题讨论】:

    标签: perl shared-memory fork


    【解决方案1】:

    不用做太多,只需在每个 if 条件下杀死一个进程。因此,在 4 个进程打印 "a selected" 后,1 被杀死,因此 "b selected 将被打印 3 次"。您需要使用它们的 PID 杀死进程。

    【讨论】:

      【解决方案2】:

      如果你绝对想要共享内存,有很多方法可以得到它:shmget,IPC::Sharable,forks::shared,...

      但在你的情况下,这绝对是矫枉过正。您可以在分叉之前简单地将所需的任何内容分配给一个变量,如下所示:

      my @test = qw( a b c );
      
      for my $test (@test) {
          my $pid  = fork;
          if (!$pid) {
              say $test;
              exit;
          }
      }
      

      或者,为了更接近您的示例:

      use List::Util qw(shuffle);
      
      my @test = shuffle (('a chosen') x 4, ('b chosen') x 3, ('c chosen') x 2);
      
      for my $test (@test) {
          my $pid  = fork;
          if (!$pid) {
              say $test;
              exit;
          }
      }
      

      【讨论】:

      • 谢谢,但我希望它每次随机选择一个(a b 或 c)。这就是为什么我需要一个计数器来计算每个已经打印了多少。
      • @user3595059,您需要子进程内部发生的随机性吗?因为在分叉之前shuffle 数组(或者使用rand,如果你更喜欢它)更容易。
      • 是的,你是对的 :) 我之前做过随机,并且没有共享内存。谢谢!
      猜你喜欢
      • 2013-06-11
      • 2012-11-04
      • 1970-01-01
      • 1970-01-01
      • 2018-08-11
      • 2012-07-21
      • 1970-01-01
      • 2015-07-04
      • 1970-01-01
      相关资源
      最近更新 更多