美文网首页
守护线程

守护线程

作者: 苏大发 | 来源:发表于2017-11-02 21:19 被阅读0次

    其一

    /*
     * php 进程管理
     */
    fclose(STDIN);
    fclose(STDOUT);
    fclose(STDERR);
    $STDIN = fopen('/dev/null', 'r');
    $STDOUT = fopen('application.log', 'wb');
    $STDERR = fopen('error.log', 'wb');
    echo '父进程:'.posix_getpid()."\r\n";
    $pid = pcntl_fork();
    //父进程和子进程都会执行下面代码
    echo '创建了子进程:'.$pid . "\r\n";
    if ($pid == -1) {
        //错误处理:创建子进程失败时返回-1.
        die('could not fork');
    } else if ($pid > 0) {
        //父进程会得到子进程号,所以这里是父进程执行的逻辑
        //pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
        echo '结束父进程'."\r\n";
        exit(0);
    } 
    //子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
    $sid = posix_setsid();  //Make the current process a session leader
    if($sid < 0){
        //-1 创建失败
        exit(1);
    }
    while(true){
        sleep(1);
        echo '守护进程在运行,时间:'.date('Y-m-d H:i:s')."\r\n";
    }
    
    

    其二

    <?php  
      
    $pid = pcntl_fork();  
      
    if ($pid == -1)  
    {  
        throw new Exception('fork子进程失败');  
    }  
    elseif ($pid > 0)  
    {  
        //父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端  
        exit(0);  
    }  
      
    // 最重要的一步,让该进程脱离之前的会话,终端,进程组的控制  
    posix_setsid();  
      
    // 修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
    // 这里重定向了根目录。在后面可以再次重定向指定文件目录  
    chdir('/');  
      
    /* 
     * 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免 
     * 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。 
     */  
    $pid = pcntl_fork();  
    if ($pid == -1)  
    {  
        throw new Exception('fork子进程失败');  
    }  
    elseif ($pid > 0)  
    {  
        //  再一次退出父进程,子进程成为最终的守护进程  
        exit(0);  
    }  
      
    // 由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符  
    fclose(STDIN);  
    fclose(STDOUT);  
    fclose(STDERR);  
      
    /* 
     * 处理业务代码 
     */  
      
    while(TRUE)  
    {  
        file_put_contents('log.txt', time().PHP_EOL, FILE_APPEND);  
        sleep(5);  
    }
    
    

    优化后

    <?php  
      
    Class Daemon{  
          
        /** 
         * 初始化一个守护进程 
         * @throws Exception 
         */  
        public function init(){  
            //创建一个子进程  
            $pid = pcntl_fork();  
              
            if ($pid == -1) {  
                throw new Exception('fork子进程失败');  
            } elseif ($pid > 0) {  
                //父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端  
                exit(0);  
            }  
              
            //创建一个新的会话,脱离终端控制,更改子进程为组长进程  
            $sid = posix_setsid();  
            if ($sid == -1) {  
                throw new Exception('setsid fail');  
            }  
              
            //修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。  
            chdir('/');  
              
            /** 
             * 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免 
             * 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。 
             */  
            $pid = pcntl_fork();  
            if ($pid == -1) {  
                throw new Exception('fork子进程失败');  
            } elseif ($pid > 0) {  
                //再一次退出父进程,子进程成为最终的守护进程  
                exit(0);  
            }  
            //由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符  
            fclose(STDIN);  
            fclose(STDOUT);  
            fclose(STDERR);  
        }  
    }  
      
    $daemon = new Daemon();  
    $daemon->init();  
      
    //处理业务代码  
    while(true) {  
        file_put_contents('/usr/local/src/log.txt', time().PHP_EOL, FILE_APPEND);  
        sleep(5);  
    } 
    

    相关文章

      网友评论

          本文标题:守护线程

          本文链接:https://www.haomeiwen.com/subject/whwapxtx.html