惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

人人都是产品经理
人人都是产品经理
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
月光博客
月光博客
雷峰网
雷峰网
Google DeepMind News
Google DeepMind News
Y
Y Combinator Blog
Microsoft Security Blog
Microsoft Security Blog
M
MIT News - Artificial intelligence
WordPress大学
WordPress大学
MongoDB | Blog
MongoDB | Blog
V
V2EX
博客园 - 【当耐特】
GbyAI
GbyAI
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
Martin Fowler
Martin Fowler
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Hugging Face - Blog
Hugging Face - Blog
B
Blog
V
Visual Studio Blog
D
DataBreaches.Net
C
Check Point Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
F
Fortinet All Blogs

WangDeer

非机动车交通规则测验 微软 50 周年壁纸是在 macOS上设计的? 「转」西二旗折叠:蜂巢经济学启示录 难得空明 Ubuntu Clean ApidocJs apigroup Support Chinese int(10)里面的10是什么意思? 5-3 会话 2021-03-25 「PHP架构师」面试准备 Laravel 上传 Docx 文件,表单验证不通过 4-4 发送信号 4-3 信号集 4-2 编写中断信号处理程序 2022-03-10 面试复盘 4-1 什么是中断信号(软中断) 3-7 进程查看 3-6 SUID特权进程 3-5多进程编写 3-4进程调度 3-2进程退出和回收 3-1进程标识与fork 2-3解释器文件 2-2命令行参数与环境参数表 2-1程序与进程 1-1课程介绍 终极复盘 第八章 传承篇 第七章 自由篇 第六章 品牌篇 第五章 作品篇
3-3进程exec
王二 · 2022-03-05 · via WangDeer

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

...