zoukankan      html  css  js  c++  java
  • php守护进程创建和简要分析

    守护进程可

    • 由系统启动脚本 /etc/rc.local
    • crontab任务,
    • 用户shell
      方式运行

    具体概念可参考c的

    进程守护化基本步骤

    • 1.创建子进程,终止父进程 (pcntl_fork,exit)
    • 2.在子进程中创建新会话 (posix_setsid)
    • 3.改变工作目录(默认继承了父进程的当前工作目录) (chdir('/'))
    • 4.重设文件掩码(默认继承了父进程的) (umask(0) 改变当前的umask为最宽松掩码)
    • 5.关闭文件描述符(默认继承了父进程打开的文件描述符) (fclose 关闭已打开的文件描述符)

    daemon.php

    <?php
    echo posix_getpid().PHP_EOL;
    
    $childs = [];
    $worker_num = 3;
    
    //daemon();
    
    for ($i = 0; $i < $worker_num; $i++) {
        fork();
    }
    while (count($childs)) {
        if (($exit_id = pcntl_wait($status)) > 0) {
            $signo = pcntl_wtermsig($status);
    
            unset($childs[$exit_id]);
        }
        if (count($childs) < $childs) {
            fork();
        }
    }
    function daemon()
    {
        $pid = pcntl_fork();
        if ($pid < 0) die("fork err");
        if ($pid == 0) {
            if (posix_setsid() <= 0) {
                die("setsid err!");
            }
            if (chdir('/') === false) {
                die("change dir err");
            }
            umask(0);
            fclose(STDIN);
            fclose(STDOUT);
            fclose(STDERR);
    
        } else {
            exit();
        }
    }
    
    function fork()
    {
        global $childs;
        $pid = pcntl_fork();
        if ($pid < 0) die("fork err");
        if ($pid == 0) {
            $child_pid = posix_getpid();
            while (true) {
                sleep(10);
            }
    
        } else {
            $parent_pid = posix_getpid();
            $childs[$pid] = $pid;
    
    
        }
    }
    
    

    分析

    不执行daeon函数时
    [root@hkui ~]# pstree -p|grep php
               |-sshd(3169)-+-sshd(10101)---bash(10103)---php(10609)-+-php(10610)
               |            |                                        |-php(10611)
               |            |                                        `-php(10612)
               
    
    
    
    [root@hkui ~]# ps --sid 10103 -o pid,ppid,pgid,sid
      PID  PPID  PGID   SID
    10103 10101 10103 10103
    10609 10103 10609 10103
    10610 10609 10609 10103
    10611 10609 10609 10103
    10612 10609 10609 10103
    
    [root@hkui ~]# ps --pid 10101 -o pid,ppid,pgid,sid
      PID  PPID  PGID   SID
    10101  3169 10101 10101
    
    [root@hkui ~]# ps --pid 3169 -o pid,ppid,pgid,sid
      PID  PPID  PGID   SID
     3169     1  3169  3169
    
    ------------------------------------------------------------------------
    bash(10103)和它创建的子进程们(10606,10610,10611,10612)属于同一个会话期
    sid为bash的进程号,所以bash为创建该会话的首进程
    bash为一个进程组 10103
    bash创建的php进程为一个进程组 
    这两个进程组同属一个会话期
    
    程序daemon.php运行时创建了进程组10609,它即为组长
    
    
    执行了daemon()
    输出
    10563
    
    [root@hkui ~]# pstree -p|grep php
               |-php(10564)-+-php(10565)
               |            |-php(10566)
               |            `-php(10567)
    
    [root@hkui ~]# ps --sid 10564 -o pid,ppid,pgid,sid
      PID  PPID  PGID   SID
    10564     1 10564 10564
    10565 10564 10564 10564
    10566 10564 10564 10564
    10567 10564 10564 10564
    
    
    执行了daemon.php后,程序运行起来了,进程id为10563
    在10563里fork一次,得到子进程10564,父进程10563退出
    子进程10564里执行setsid后发生了主要的以下三件事
        1.10564创建了新的进程组,自己升级为组长
        2.10564创建了新的会话组,并成为该会话组的会话首进程
        3.10564和控制终端失去联系
    由于其父进程10563退出,它的父进程变为init进程
    在10564里fork了3个子进程,继承了10564的组Id,会话Id
    
    
    
  • 相关阅读:
    C++11 std标准库chrono获取系统时间戳
    求取激光光斑质心
    Windows多网卡UDP广播问题
    IP地址分类
    C++各种时间的含义、区别和相互转换
    MFC中控件显示提示信息tooltip
    IP地址 网关 子网掩码之间的关系
    MFC动态添加菜单选项
    opencv函数学习:rotate()的使用
    opencv函数学习:flip()的使用
  • 原文地址:https://www.cnblogs.com/HKUI/p/10848243.html
Copyright © 2011-2022 走看看