多进程03-查看创建退出

154 阅读1分钟

进程查看

  1. 相关指令
    • pstree 查看进程树状结构
    • ps 进程信息
    • top 系统负载
  2. 进程信息
    • user 归属用
    • tty 终端,守护进程没有这个。一般都是模拟终端
    • stat S R 进程状态
    • time 运行时间
    • command 进程启动指令
    • pr 进程优先级
    • ni nice值越小,优先级越高
    • mem 内存使用
    • swap 交换分区
  3. 关键字概念
    • pid 进程id
    • ppid 父进程id
    • pgid 进程组长id
    • sid 回话id
    • uid 用户id
    • gid 进程组id
    • euid 有效用户id
    • egid 有效组egid
  4. 进程文件夹信息proc/pid
    • cmdline 启动命令
    • cwd 工作目录
    • envision 环境参数表
    • exe 可执行文件
    • fd 文件描述符
    • fdinfo 偏移权限等
    • limits 各种限制。
    • status
  5. 概念
    • 孤儿进程。父进程退出,子进程归属为0号进程
    • 僵尸进程。子进程退出,父进程未回收资源,则子进程相关信息一直保留,浪费资源
    • 进程优先级

创建&退出

  1. 实验代码结构:
// 总体结构
$pid = pcntl_fork();
if ($pid == 0){
    printf("child process :%d.".PHP_EOL, posix_getpid());
    childProcess();
}elseif ($pid > 0){
    sleep(2);
    printf("parent process :%d. child:%d ".PHP_EOL, posix_getpid(), $pid);
    parentProcess();
}
// 各个实验修改的代码
function childProcess(){}
function parentProcess(){}
  1. 孤儿进程
// childProcess 添加死循环. 父进程退出子进程仍在继续执行
function childProcess(){
    while(1){
        sleep(3);
        Printf(__FUNCTION__. " child %d sleep".PHP_EOL, posix_getpid());
    }
}
  1. 僵尸进程 zombie
// 子进程结束,父进程并没有回收子进程资源
// parentProcess  添加死循环
function childProcess(){
    printf("im child process %d, im out".PHP_EOL, posix_getpid());
}
function parentProcess(){
    while(1){
        sleep(3);
        Printf(__FUNCTION__. " child %d sleep".PHP_EOL, posix_getpid());
    }
}

image-20210529132824467.png

  1. 进程退出
// 子进程死循环
function childProcess(){
    while (1){
        sleep(2);
        printf(__FUNCTION__ . " process :%d. running".PHP_EOL, posix_getpid());
    }
}
// 实验一: 阻塞wait  pacntl_wait
// 模拟子进程 发送结束信号
// 发送命令  kill childPId 
function parentProcess(){
    // 测试监听
    $exitPid = pcntl_wait($status);
    if ($exitPid < 0){
        printf("error".PHP_EOL);
    }else{
        printf(__FUNCTION__ . " process:%d out  out status:%d ".
            PHP_EOL, $exitPid, pcntl_wexitstatus($status));
    }

    printf("%s func over \n", __FUNCTION__);
}

// 实验二:非阻塞wait WNOHANG
function parentProcess(){
    // 测试监听
    while (1){
        $exitPid = pcntl_wait($status, WNOHANG);
        if ($exitPid < 0){
            printf("error".PHP_EOL);
        }elseif ($exitPid == 0){
            sleep(2);
            printf("havn't child out".PHP_EOL);
        }else{
            printf(__FUNCTION__ . " process:%d out  out status:%d ".
                PHP_EOL, $exitPid, pcntl_wexitstatus($status)); // 正常 
            break;
        }
    }
    printf("%s func over \n", __FUNCTION__);
}

// 实验四 错误信息
$exitPid = pcntl_wait($status);
$err = pcntl_errno();
print_r(pcntl_strerror($err));

// 实验五:进程退出的几种信息
// 1、信号退出  pcntl_wifsignaled判断是否是信号。pcntl_wtermsig获取退出信号
if (pcntl_wifsignaled($status)){
    printf(__FUNCTION__ . " process:%d out  singggggg status:%d ".
           PHP_EOL, $exitPid, pcntl_wtermsig($status));// 信号退出
    break;
}
// 2、正常退出  wifexited wexitstatus
if (pcntl_wifexited($status)){
    printf(__FUNCTION__ . " process:%d out  out status:%d ".
           PHP_EOL, $exitPid, pcntl_wexitstatus($status));// 正常退出 获取退出状态码
    break;
}
// 3、停止退出  pcntl_wifstopped   pcntl_wstopsig
if(pcntl_wifstopped($status)){
    printf(__FUNCTION__ . " process:%d out  stop status:%d ".
           PHP_EOL, $exitPid, pcntl_wstopsig($status));// stop stp 暂停。可通过 sign cont 恢复
}
  1. exec
  • exec 函数:执行程序
  • pcntl 的进程扩展, pcntl_exec 内部的系统函数调用是 execve
  • 一般用法,父进程创建子进程,然后子进程调用这个函数
  • 代码段 + 数据段 会被新程序替换,一些属性会继承父进程,pid并没有发生变化
  • 调用的必须是可执行程序。 elf, php源码文件不可。php解释器,或者php解释器文件赋予 x权限
// 1、调用程序
function showId($str)
{
    fprintf(STDOUT, "%s pid=%d, ppid=%d, gpid=%d, sid=%d, uid=%d, gid=%d\n",
        $str,
        posix_getpid(),
        posix_getppid(),
        posix_getpgid(posix_getpid()),
        posix_getsid(posix_getpid()),
        posix_getuid(),
        posix_getgid()
    );
}
showId("parent: ");
$pid = pcntl_fork();
if ($pid == 0){
    // 子进程
    showId("child:");
    pcntl_exec("./run2", ["aaa","ccc", "aaa"], ["a"=>"aaaa"]);
}elseif($pid > 0){
    // 父进程
    sleep(2);
}else{
    fprintf(STDOUT, "create child process err \n");
}
fprintf(STDOUT, "process:%d out \n", posix_getpid());

// pcntl_exec("run2.php",["a"],["ab"]);
// pcntl_exec("/usr/bin/php",["run2.php","abc","123"],["test"]);
// pcntl_exec("./run2", ["aaa","ccc", "aaa"], ["a"=>"aaaa"]);

// 2、被调用程序
#! /opt/rh/rh-php72/root/usr/bin/php
<?php

echo "aaa".PHP_EOL;
var_dump($argv);
var_dump(getenv());