php守护进程

守护进程可

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

具体概念可参考c的

进程守护化基本步骤

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

daemon.php

<?phpecho 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   SID10103 10101 10103 1010310609 10103 10609 1010310610 10609 10609 1010310611 10609 10609 1010310612 10609 10609 10103[root@hkui ~]# ps --pid 10101 -o pid,ppid,pgid,sid  PID  PPID  PGID   SID10101  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为一个进程组 10103bash创建的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   SID10564     1 10564 1056410565 10564 10564 1056410566 10564 10564 1056410567 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
©著作权归作者所有:来自51CTO博客作者hkui2010的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 进程终止,环境表以及在内存中布局和非局部跳转
  2. Linux运维入门教程06-02 (系统的初始化和服务)
  3. Cassandra排查 | 记一次Cassandra Java堆外内存排查经历
  4. Linux之常用基础命令简介
  5. 浅析集群会话绑定tomcat cluster session
  6. 想用Python爬小姐姐图片?那你得先搞定分布式进程
  7. 进程间通信
  8. ORA-29770: global enqueue process LMS hang for 70
  9. 看图说话,脏读、不可重复读、幻读分别是什么?

随机推荐

  1. redis之发布与订阅
  2. Java线程之线程的调度-休眠
  3. Java 的版本历史与特性
  4. Java线程之线程的调度-优先级
  5. Java 中关于 String 类型的 10 个问题
  6. 使用 ThreadLocal 变量的时机和方法
  7. JDK1.8 ConcurrentHashMap的size
  8. 手把手教你用 Java 实现 AOP
  9. 谁在关心 toString 的性能
  10. 线程池调整真的很重要