perl fork

https://www.cnblogs.com/f-ck-need-u/p/9693675.htmlhtml

fork是低层次的系统调用,经过复制父进程来建立子进程。shell

#!/usr/bin/perl
use 5.010;
my $pid=fork();
say $pid, "========";

 

fork用来拷贝当前进程,生成一个基本彻底同样的子进程。less

my $pid=fork();

若是fork成功:spa

  • 则表示成功建立子进程,这时会有两条执行路线:继续执行父进程、执行子进程
  • fork成功时,会返回两个值:对父进程返回子进程的pid,对子进程返回0

若是fork失败,将对父进程返回undef,并设置错误信息。fork失败的可能缘由有:code

      • 内核内存不够,没法申请内存来fork
      • 达到了容许的最大进程数量(进程数上限)
      • 达到了rlimit限制的某种资源上限

执行该程序,将返回两行数据:orm

1
262620====== 0======

其中第一行输出是父进程输出的,第二行是子进程输出的。htm

虽然这里父进程先输出,但fork成功以后,父、子进程并无执行的前后顺序,也可能cpu会先调度到上子进程去执行。blog

root@vm3110 [11:06:32 AM] [~/test_perl] 
-> # ./testfork.pl
30598========
0========
root@vm3110 [11:06:33 AM] [~/test_perl] 
-> # ./testfork.pl
30608========
root@vm3110 [11:06:34 AM] [~/test_perl] 
-> # 0========
./testfork.pl
0========
30618========

 

 

 注意上图中子进程部分只画了"say"那行语句,但实际上子进程是彻底复制父进程的,子进程也能够有say前面的那段语句(好比那个fork语句),进程

但因为父进程的状态已经执行完了fork,因此子进程也是从fork语句以后开始执行的,fork语句以前的语句对于子进程来讲是透明的。ip

并且按照写时复制的技术,子进程用不到它因此不会复制fork前面的代码(注:也就是说子进程和父进程是共享代码的)。

 

更复杂的例子

#!/usr/bin/perl
use 5.010;
print "id1: ", $pid, "\n";
my $pid=fork;
print "id2: ",$pid,"\n";
if (!$pid) {
	say "child process: ",$pid;
}
waitpid($pid, 0);
say "parent process: ", $pid;

 

id1: 
id2: 30678
id2: 0
child process: 0
parent process: 0
parent process: 30678

 

首先perl进程输出id1。而后fork一个子进程,这时有两条执行路线。假如fork后先执行父进程,则:

  • 此父进程将输出id2
  • 而后判断pid的值,由于fork返回给父进程的的pid变量值为子进程的进程号,因此不会等于0,因而if判断不经过
  • 继续执行waitpid(),它将等待子进程执行结束,如下是子进程的执行过程:
    • 子进程首先输出id2
    • 而后判断$pid,因为fork返回给子进程的pid变量值为0,因此if判断经过,因而子进程输出"child process"
    • 继续执行waitpid(),因为$pid=0,waitpid()的等待pid为0时,表示等待以本身为leader进程的进程组中的其它进程,因为没有进程组,因此waitpid失败
    • 继续执行,输出"parent process"
    • 子进程执行完毕
  • 父进程的waitpid()等待子进程执行完毕,继续向下执行
  • 父进程输出"parent process"

假如fork以后,先执行子进程,且还先把子进程执行完了,cpu才调度到父进程,则也没有影响,子进程执行完毕后,早晚会调度到父进程,而父进程的waitpid($pid)已经没有子进程了,因而waitpid()失败(返回-1),继续向下执行。

 

 

显然,上面fork的代码有一些问题。因为fork建立子进程以后。父、子进程都继续执行,且执行的前后顺序不定。因此:

  1. 在fork以后,应该紧接着判断是不是子进程,避免有些在操做父子中都执行
  2. 在父进程中等待子进程
  3. 在子进程中加入执行完后就退出子进程的动做,省得执行本该父进程执行的动做

大概代码以下:

my $pid=fork;
unless($pid){   # 判断子进程的语句紧跟着fork
    CODE1;
    exit;       # 要让子进程退出
}
waitpid($pid,0);  # 要等待子进程
CODE2;

 fork和exec结合

通常fork和exec会一块儿用,fork用来建立新的子进程,exec启动一个程序替代当前子进程并在子进程结束时退出子进程。

例如system "date"命令,替换为低层次的fork+exec+waitpid。

#!/usr/bin/perl
use 5.010;
defined(my $pid=fork) or die "Cannot fork: $!";
unless($pid) {
#进入到这里执行的,表示进入子进程
     exec 'date'; # exec正确执行时,执行完后将结束子进程
     die "cannot exec date: $!";  #exec 启动失败时,将执行die来结束子进程
}
#这里表示是父进程,由于exec执行的子进程自动结束了子进程。
waitpid($pid, 0);

 

Tue Dec 10 11:26:13 CST 2019
pid => 30813.

 system、exec、fork等的区别

第一我的解释:

  • exec replaces the current process with another one.
  • system runs another program, wait for its completion.
  • fork copies the current process; both the original and the copy continue from the same point.
  • pipe sets up a pipe between two handles.
  • syscall makes a low-level system call.
  • eval executes (the string form will first compile) a piece of Perl code.

第二我的解释:

    • exec is used to execute the given process by replacing the current process. If the given process get executed successfully then exec will not return the value. exec returns the value in case of failure only.
    • System is also doing the same thing as exec but system returns value in both success and failure cases. And parent process waits for the child process to complete. System() runs the command through a shell,while exec() runs the command directly.
    • fork is used to create a new process(child process). And it is returning the PID of child to parent and zero to child if the fork is successful. The difference between the fork and exec is exec replaces the current process but fork doesn't.
    • pipe is used for communicating between two processes. We can use both named and nameless pipes. It returns open a pair of pipes. In one end we can write. And in another end we can read the content.
    • syscall is used to call the system call which is specified as a first argument. Remaining elements are the arguments to the system call.
相关文章
相关标签/搜索