pcntl_exec 函数用来执行一个程序,它内部的系统调用是 execve

一般的用法是父进程先创建一个子进程,然后子进程调用这个函数,正文段(代码段)+ 数据段会被新程序替换,它的一些属性会继承父进程,PID并没有发生变化。

execve() executes the program referred to by pathname. This causes the program that is currently being run by the calling process to be replaced with a new program, with newly initialized stack, heap, and (initialized and uninitialized) data segments.

pathname must be either a binary executable, or a script starting with a line of the form:

#!interpreter [optional-arg]

——execve

示例:

demo7.php

<?php

function showID($str)
{
    $pid = posix_getpid();

    fprintf(
        STDOUT,
        "%s pid=%d,ppid=%d,gpid=%d,sid=%d,uid=%d,gid=%d\n",
        $str,
        $pid,
        posix_getppid(),
        posix_getpgrp(),
        posix_getsid($pid),
        posix_getuid(),
        posix_getgid()
    );
}

showID("parent:");

$pid = pcntl_fork();

if (0 == $pid) {

    pcntl_exec('/usr/bin/php', ['demo2.php', 'a', 'b', 'c']);

    echo "hello world"; // 不会执行,
}


$exitPid = pcntl_wait($status);

if ($exitPid > 0){
    fprintf(STDOUT,"exit pid=%d\n",$exitPid);
}

demo2.php

<?php
function showID($str)
{
    $pid = posix_getpid();

    fprintf(
        STDOUT,
        "%s pid=%d,ppid=%d,gpid=%d,sid=%d,uid=%d,gid=%d\n",
        $str,
        $pid,
        posix_getppid(),
        posix_getpgrp(),
        posix_getsid($pid),
        posix_getuid(),
        posix_getgid()
    );
}

showId('child:');

运行结果:

$ php demo7.php 
parent: pid=1465,ppid=59,gpid=1465,sid=59,uid=1000,gid=1000
child: pid=1466,ppid=1465,gpid=1465,sid=59,uid=1000,gid=1000
exit pid=1466

通过 strace -f -s 65500 -o demo7.log php demo7.php 查看系统调用:

2227  execve("/usr/bin/php", ["php", "demo7.php"], 0x7ffeba4701b0 /* 53 vars */) = 0

...

// 创建子进程
2227  clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f08921d7c50) = 2228

...


2227  getpid()                          = 2227
2227  getppid()                         = 2225
2227  getpgrp()                         = 2225
2227  getsid(2227)                      = 59
2227  getuid()                          = 1000
2227  getgid()                          = 1000
2227  write(1, "parent: pid=2227,ppid=2225,gpid=2225,sid=59,uid=1000,gid=1000\n", 62) = 62

// 运行 demo2.php
2228  execve("/usr/bin/php", ["/usr/bin/php", "demo2.php", "a", "b", "c"], 0x555801030e70 /* 53 vars */) = 0

...

2228  getpid()                          = 2228
2228  getppid()                         = 2227
2228  getpgrp()                         = 2225
2228  getsid(2228)                      = 59
2228  getuid()                          = 1000
2228  getgid()                          = 1000
2228  write(1, "child: pid=2228,ppid=2227,gpid=2225,sid=59,uid=1000,gid=1000\n", 61) = 61

...