Perl 进程管理

  • 进程管理

    您可以按照各种要求使用 Perl 来创建新流程。本教程将列出创建和管理Perl流程的一些重要且最常用的方法。
    • 您可以使用特殊变量$$$PROCESS_ID来获取当前进程ID。
    • 使用任何上述方法创建的每个进程都使用%ENV变量维护其自己的虚拟环境。
    • exit() 函数总是退出刚子的过程,执行此功能和主要过程作为一个整体将不会退出,除非所有运行的子流程都已经退出。
    • 所有打开的句柄在子进程中都是 dup()-ed,因此在一个进程中关闭任何句柄不会影响其他进程。
  • backstick 操作符

    执行任何Unix命令的最简单方法是使用 backstick 运算符。您只需将命令放入 backstick 运算符中,这将导致命令执行并返回其结果,该结果可以存储如下:
    
    @files = `ls -l`;
    
    foreach $file (@files) {
       print $file;
    }
    
    1;
    
    执行以上代码后,它将列出当前目录中可用的所有文件和目录-
    
    drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
    drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
    -rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
    drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
    -rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
    drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy
    
  • system() 函数

    您还可以使用system() 函数执行任何Unix命令,其输出将进入perl脚本的输出。默认情况下,它是屏幕,即STDOUT,但是您可以使用重定向操作符将其重定向到任何文件>-
    
    system( "ls -l")
    
    1;
    
    当执行上述代码时,它列出了当前目录中可用的所有文件和目录-
    
    drwxr-xr-x 3 root root 4096 Sep 14 06:46 9-14
    drwxr-xr-x 4 root root 4096 Sep 13 07:54 android
    -rw-r--r-- 1 root root  574 Sep 17 15:16 index.htm
    drwxr-xr-x 3  544  401 4096 Jul  6 16:49 MIME-Lite-3.01
    -rw-r--r-- 1 root root   71 Sep 17 15:16 test.pl
    drwx------ 2 root root 4096 Sep 17 15:11 vAtrJdy
    
    当命令包含$PATH或$HOME之类的shell环境变量时,请务必小心。尝试以下三种情况-
    
    
    $PATH = "I am Perl Variable";
    
    system('echo $PATH');  # Treats $PATH as shell variable
    system("echo $PATH");  # Treats $PATH as Perl variable
    system("echo \$PATH"); # Escaping $ works.
    
    1;
    
    执行上述代码时,根据shell变量$PATH中的设置,它会产生以下结果。
    
    /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
    I am Perl Variable
    /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin
    
  • fork() 函数

    Perl提供了一个fork() 函数,该函数对应于同名的Unix系统调用。在大多数使用fork() 系统调用的类Unix平台上,Perl的fork() 只是对其进行调用。在某些平台(例如Windows)上,不能使用fork() 系统调用,可以构建Perl在解释器级别上模拟fork() 。
    fork() 函数用于克隆当前进程。该调用将在同一点创建一个运行相同程序的新进程。它将子pid返回到父进程,将0返回到子进程,如果fork不成功,则返回undef。您可以在进程中使用exec() 函数启动请求的可执行文件,该可执行文件将在单独的进程区域中执行,并且exec() 将等待其完成,然后以与该进程相同的退出状态退出。
    
    
    if(!defined($pid = fork())) {
       # fork returned undef, so unsuccessful
       die "Cannot fork a child: $!";
    } elsif ($pid == 0) {
       print "Printed by child process\n";
       exec("date") || die "can't exec date: $!";
      
    } else {
       # fork returned 0 nor undef
       # so this branch is parent
       print "Printed by parent process\n";
       $ret = waitpid($pid, 0);
       print "Completed process id: $ret\n";
    
    }
    
    1;
    
    执行上述代码后,将产生以下结果-
    
    Printed by parent process
    Printed by child process
    Tue Sep 17 15:41:08 CDT 2013
    Completed process id: 17777
    
    可以将wait() 和waitpid() 作为fork() 返回的伪进程ID进行传递。这些调用将适当地等待伪进程的终止并返回其状态。如果使用waitpid() 函数在没有等待孩子的情况下进行分叉,则会堆积僵尸。在Unix系统上,可以通过将$ SIG {CHLD}设置为“ IGNORE”来避免这种情况,如下所示:
    
    
    local $SIG{CHLD} = "IGNORE";
     
    if(!defined($pid = fork())) {
       # fork returned undef, so unsuccessful
       die "Cannot fork a child: $!";
    } elsif ($pid == 0) {
       print "Printed by child process\n";
       exec("date") || die "can't exec date: $!";
      
    } else {
       # fork returned 0 nor undef
       # so this branch is parent
       print "Printed by parent process\n";
       $ret = waitpid($pid, 0);
       print "Completed process id: $ret\n";
    
    }
    
    1;
    
    
    尝试一下
    执行上述代码后,将产生以下结果-
    
    Printed by parent process
    Printed by child process
    Tue Sep 17 15:44:07 CDT 2013
    Completed process id: -1
    
  • kill() 函数

    Perl kill('KILL',(Process List))函数可用于通过将fork() 返回的ID传递给伪进程来终止它。
    请注意,在伪process() 上使用kill('KILL',(Process List))通常可能导致内存泄漏,因为实现伪进程的线程没有机会清理其资源。
    您可以使用kill() 函数将任何其他信号发送到目标进程,例如,下面的命令会将SIGINT发送到进程ID 104和102-
    
    
    kill('INT', 104, 102);
     
    1;