亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

php 守護進程(Daemon)

2020-03-22 18:40:16
字體:
來源:轉載
供稿:網友
本篇文章給大家分享的內容是關于php 守護進程(Daemon),有著一定的參考價值,有需要的朋友可以參考一下

守護進程(Daemon)是運行在后臺的一種特殊進程。它獨立于控制終端并且周期性地執行某種任務或等待處理某些發生的事件。守護進程是一種很有用的進程。php也可以實現守護進程的功能。

1、基本概念

進程

每個進程都有一個父進程,子進程退出,父進程能得到子進程退出的狀態。

進程組

每個進程都屬于一個進程組,每個進程組都有一個進程組號,該號等于該進程組組長的PID

2、守護編程要點

1. 在后臺運行。
為避免掛起控制終端將Daemon放入后臺執行。方法是在進程中調用fork使父進程終止,讓Daemon在子進程中后臺執行。 if($pid=pcntl_fork()) exit(0);//是父進程,結束父進程,子進程繼續
2. 脫離控制終端,登錄會話和進程組
有必要先介紹一下Linux中的進程與控制終端,登錄會話和進程組之間的關系:進程屬于一個進程組,進程組號(GID)就是進程組長的進程號(PID)。登錄會話可以包含多個進程組。這些進程組共享一個控制終端。這個控制終端通常是創建進程的登錄終 端。 控制終端,登錄會話和進程組通常是從父進程繼承下來的。我們的目的就是要擺脫它們,使之不受它們的影響。方法是在第1點的基礎上,調用setsid()使進程成為會話組長: posix_setsid();
說明:當進程是會話組長時setsid()調用失敗。但第一點已經保證進程不是會話組長。setsid()調用成功后,進程成為新的會話組長和新的進程組長,并與原來的登錄會話和進程組脫離。由于會話過程對控制終端的獨占性,進程同時與控制終端脫離。
3. 禁止進程重新打開控制終端
現在,進程已經成為無終端的會話組長。但它可以重新申請打開一個控制終端??梢酝ㄟ^使進程不再成為會話組長來禁止進程重新打開控制終端: if($pid=pcntl_fork()) exit(0);//結束第一子進程,第二子進程繼續(第二子進程不再是會話組長)
4. 關閉打開的文件描述符
進程從創建它的父進程那里繼承了打開的文件描述符。如不關閉,將會浪費系統資源,造成進程所在的文件系統無法卸下以及引起無法預料的錯誤。按如下方法關閉它們:
fclose(STDIN),fclose(STDOUT),fclose(STDERR)關閉標準輸入輸出與錯誤顯示。
5. 改變當前工作目錄
進程活動時,其工作目錄所在的文件系統不能卸下。一般需要將工作目錄改變到根目錄。對于需要轉儲核心,寫運行日志的進程將工作目錄改變到特定目錄如chdir("/")
6. 重設文件創建掩模
進程從創建它的父進程那里繼承了文件創建掩模。它可能修改守護進程所創建的文件的存取位。為防止這一點,將文件創建掩模清除:umask(0);
7. 處理SIGCHLD信號
處理SIGCHLD信號并不是必須的。但對于某些進程,特別是服務器進程往往在請求到來時生成子進程處理請求。如果父進程不等待子進程結束,子進程將成為僵尸進程(zombie)從而占用系統資源。如果父進程等待子進程結束,將增加父進程的負擔,影 響服務器進程的并發性能。在Linux下可以簡單地將SIGCHLD信號的操作設為SIG_IGN。 signal(SIGCHLD,SIG_IGN);
這樣,內核在子進程結束時不會產生僵尸進程。這一點與BSD4不同,BSD4下必須顯式等待子進程結束才能釋放僵尸進程。關于信號的問題請參考Linux 信號說明列表

  1. <?php  /** *@author tengzhaorong@gmail.com *@date 2013-07-25 * 后臺腳本控制類 */  html' target='_blank'>class DaemonCommand{         private $info_dir="/tmp";      private $pid_file="";      private $terminate=false; //是否中斷      private $workers_count=0;      private $gc_enabled=null;      private $workers_max=8; //最多運行8個進程         public function __construct($is_sington=false,$user='nobody',$output="/dev/null"){                 $this->is_sington=$is_sington; //是否單例運行,單例運行會在tmp目錄下建立一個唯一的PID              $this->user=$user;//設置運行的用戶 默認情況下nobody              $this->output=$output; //設置輸出的地方              $this->checkPcntl();      }      //檢查環境是否支持pcntl支持      public function checkPcntl(){          if ( ! function_exists('pcntl_signal_dispatch')) {              // PHP < 5.3 uses ticks to handle signals instead of pcntl_signal_dispatch              // call sighandler only every 10 ticks              declare(ticks = 10);          }             // Make sure PHP has support for pcntl          if ( ! function_exists('pcntl_signal')) {              $message = 'PHP does not appear to be compiled with the PCNTL extension.  This is neccesary for daemonization';              $this->_log($message);              throw new Exception($message);          }          //信號處理          pcntl_signal(SIGTERM, array(__CLASS__, "signalHandler"),false);          pcntl_signal(SIGINT, array(__CLASS__, "signalHandler"),false);          pcntl_signal(SIGQUIT, array(__CLASS__, "signalHandler"),false);             // Enable PHP 5.3 garbage collection          if (function_exists('gc_enable'))          {              gc_enable();              $this->gc_enabled = gc_enabled();          }      }         // daemon化程序      public function daemonize(){             global $stdin, $stdout, $stderr;          global $argv;             set_time_limit(0);             // 只允許在cli下面運行          if (php_sapi_name() != "cli"){              die("only run in command line mode/n");          }             // 只能單例運行          if ($this->is_sington==true){                 $this->pid_file = $this->info_dir . "/" .__CLASS__ . "_" . substr(basename($argv[0]), 0, -4) . ".pid";              $this->checkPidfile();          }             umask(0); //把文件掩碼清0             if (pcntl_fork() != 0){ //是父進程,父進程退出              exit();          }             posix_setsid();//設置新會話組長,脫離終端             if (pcntl_fork() != 0){ //是第一子進程,結束第一子進程                 exit();          }             chdir("/"); //改變工作目錄             $this->setUser($this->user) or die("cannot change owner");             //關閉打開的文件描述符          fclose(STDIN);          fclose(STDOUT);          fclose(STDERR);             $stdin  = fopen($this->output, 'r');          $stdout = fopen($this->output, 'a');          $stderr = fopen($this->output, 'a');             if ($this->is_sington==true){              $this->createPidfile();          }         }      //--檢測pid是否已經存在      public function checkPidfile(){             if (!file_exists($this->pid_file)){              return true;          }          $pid = file_get_contents($this->pid_file);          $pid = intval($pid);          if ($pid > 0 && posix_kill($pid, 0)){              $this->_log("the daemon process is already started");          }          else {              $this->_log("the daemon proces end abnormally, please check pidfile " . $this->pid_file);          }          exit(1);         }      //----創建pid      public function createPidfile(){             if (!is_dir($this->info_dir)){              mkdir($this->info_dir);          }          $fp = fopen($this->pid_file, 'w') or die("cannot create pid file");          fwrite($fp, posix_getpid());          fclose($fp);          $this->_log("create pid file " . $this->pid_file);      }         //設置運行的用戶      public function setUser($name){             $result = false;          if (empty($name)){              return true;          }          $user = posix_getpwnam($name);          if ($user) {              $uid = $user['uid'];              $gid = $user['gid'];              $result = posix_setuid($uid);              posix_setgid($gid);          }          return $result;         }      //信號處理函數      public function signalHandler($signo){             switch($signo){                 //用戶自定義信號              case SIGUSR1: //busy              if ($this->workers_count < $this->workers_max){                  $pid = pcntl_fork();                  if ($pid > 0){                      $this->workers_count ++;                  }              }              break;              //子進程結束信號              case SIGCHLD:                  while(($pid=pcntl_waitpid(-1, $status, WNOHANG)) > 0){                      $this->workers_count --;                  }              break;              //中斷進程              case SIGTERM:              case SIGHUP:              case SIGQUIT:                     $this->terminate = true;              break;              default:              return false;          }         }      /**     *開始開啟進程     *$count 準備開啟的進程數     */      public function start($count=1){             $this->_log("daemon process is running now");          pcntl_signal(SIGCHLD, array(__CLASS__, "signalHandler"),false); // if worker die, minus children num          while (true) {              if (function_exists('pcntl_signal_dispatch')){                     pcntl_signal_dispatch();              }                 if ($this->terminate){                  break;              }              $pid=-1;              if($this->workers_count<$count){                     $pid=pcntl_fork();              }                 if($pid>0){                     $this->workers_count++;                 }elseif($pid==0){                     // 這個符號表示恢復系統對信號的默認處理                  pcntl_signal(SIGTERM, SIG_DFL);                  pcntl_signal(SIGCHLD, SIG_DFL);                  if(!empty($this->jobs)){                      while($this->jobs['runtime']){                          if(empty($this->jobs['argv'])){                              call_user_func($this->jobs['function'],$this->jobs['argv']);                          }else{                              call_user_func($this->jobs['function']);                          }                          $this->jobs['runtime']--;                          sleep(2);                      }                      exit();                     }                  return;                 }else{                     sleep(2);              }                }             $this->mainQuit();          exit(0);         }         //整個進程退出      public function mainQuit(){             if (file_exists($this->pid_file)){              unlink($this->pid_file);              $this->_log("delete pid file " . $this->pid_file);          }          $this->_log("daemon process exit now");          posix_kill(0, SIGKILL);          exit(0);      }         // 添加工作實例,目前只支持單個job工作      public function setJobs($jobs=array()){             if(!isset($jobs['argv'])||empty($jobs['argv'])){                 $jobs['argv']="";             }          if(!isset($jobs['runtime'])||empty($jobs['runtime'])){                 $jobs['runtime']=1;             }             if(!isset($jobs['function'])||empty($jobs['function'])){                 $this->log("你必須添加運行的函數!");          }             $this->jobs=$jobs;         }      //日志處理      private  function _log($message){          printf("%s/t%d/t%d/t%s/n", date("c"), posix_getpid(), posix_getppid(), $message);      }     }     //調用方法1  $daemon=new DaemonCommand(true);  $daemon->daemonize();  $daemon->start(2);//開啟2個子進程工作  work();              //調用方法2  $daemon=new DaemonCommand(true);  $daemon->daemonize();  $daemon->addJobs(array('function'=>'work','argv'=>'','runtime'=>1000));//function 要運行的函數,argv運行函數的參數,runtime運行的次數  $daemon->start(2);//開啟2個子進程工作     //具體功能的實現  function work(){        echo "測試1";  }  ?>

相關推薦:

PHP進程間通信詳解

總結關于PHP進程通信注意點

以上就是php 守護進程(Daemon)的詳細內容,更多請關注 其它相關文章!

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
久久精品欧美视频| 国产亚洲美女久久| 精品国产一区二区三区久久| 精品久久香蕉国产线看观看gif| 91精品国产高清自在线看超| 亚洲精品720p| 亚洲精品福利在线观看| 久久久久久久久久av| 欧美激情视频在线免费观看 欧美视频免费一| 国产精品视频男人的天堂| 狠狠躁18三区二区一区| 亚洲国产成人久久| 亚洲人成电影网站色xx| 亚洲午夜精品久久久久久久久久久久| 国产精品678| 日韩av免费看网站| 日韩69视频在线观看| 亚洲人成人99网站| 成人免费午夜电影| 日韩美女在线播放| 日韩经典中文字幕在线观看| 日韩免费看的电影电视剧大全| 91国产一区在线| 97国产成人精品视频| 亚洲字幕在线观看| 亚洲级视频在线观看免费1级| 欧美成人免费在线视频| 少妇高潮久久久久久潘金莲| 欧美亚洲成人免费| 国产欧美一区二区三区久久| 国产精品美女www爽爽爽视频| 中文字幕亚洲欧美在线| 狠狠综合久久av一区二区小说| 久久精品视频导航| 伊人av综合网| 亚洲人成伊人成综合网久久久| 日韩av快播网址| 国内精品小视频在线观看| 欧美性xxxx极品高清hd直播| 色无极影院亚洲| 91久久久在线| 国产一区二区三区四区福利| 欧美精品videos性欧美| 国产91对白在线播放| 欧美裸体男粗大视频在线观看| 日韩午夜在线视频| 成人a视频在线观看| 国产精品一区二区女厕厕| 国产亚洲欧洲高清一区| 国产亚洲激情视频在线| 91国产在线精品| 国产有码一区二区| 国模极品一区二区三区| 日韩视频永久免费观看| 亚洲最新av在线网站| 在线成人中文字幕| 国产精品久久9| 福利精品视频在线| 亚洲激情在线观看视频免费| 久久精品国产一区二区电影| 日韩一区二区欧美| 亚洲免费电影在线观看| 国产欧美一区二区白浆黑人| 日韩精品视频免费在线观看| 亚洲精品视频免费| 国产91精品高潮白浆喷水| xvideos亚洲| 大伊人狠狠躁夜夜躁av一区| 亚洲欧美在线免费观看| 欧美一级大片视频| 国产精品久久久久久久久借妻| 91免费在线视频| 欧美日韩中文在线观看| 97香蕉超级碰碰久久免费软件| 日韩在线播放一区| 亚洲精品国偷自产在线99热| 国产一区视频在线| 日韩成人av网| 日韩激情视频在线播放| 亚洲人成网站777色婷婷| 97视频在线观看免费| 亚洲iv一区二区三区| 日本最新高清不卡中文字幕| 欧美激情一区二区三区成人| 成人久久18免费网站图片| 性欧美xxxx视频在线观看| 国产精品自产拍在线观| 日韩电影中文字幕| 国产精品福利观看| 亚洲国产精品va在线看黑人| 亚洲女人天堂av| 日韩视频―中文字幕| 久久免费精品视频| 亚洲精品在线观看www| 国产成人aa精品一区在线播放| 国产精品久久久久久久电影| 91天堂在线视频| 欧美乱大交xxxxx另类电影| 91精品国产网站| 81精品国产乱码久久久久久| 最近中文字幕mv在线一区二区三区四区| 国模叶桐国产精品一区| 青青草原成人在线视频| 日韩69视频在线观看| 亚洲一区二区三区四区视频| 中文字幕久精品免费视频| 国产精品久久久精品| 亚洲精品国产福利| 精品久久久久久久久久久久久久| 午夜精品一区二区三区视频免费看| 精品国产一区二区三区四区在线观看| 日本午夜精品理论片a级appf发布| 国产精品一区二区电影| 久久999免费视频| 欧美激情一级精品国产| 91福利视频在线观看| 91在线|亚洲| 久国内精品在线| 欧美成人免费全部观看天天性色| 亚洲xxx视频| 欧美多人乱p欧美4p久久| 国产在线视频91| 亚洲精美色品网站| 亚洲男人的天堂在线播放| 亚洲精品一区二区久| 最近2019免费中文字幕视频三| 久久在线观看视频| 国产一区二区三区18| 久久91精品国产| 青青在线视频一区二区三区| 中文字幕久精品免费视频| 国产福利精品av综合导导航| www.日韩欧美| 91久久精品国产91久久| 国产亚洲精品久久久| 亚洲欧美变态国产另类| 日韩av在线导航| 国产日韩中文在线| 日韩在线一区二区三区免费视频| 清纯唯美亚洲综合| 欧美一区二区三区艳史| 久久福利视频网| 欧美一级免费视频| 国产va免费精品高清在线观看| 人人爽久久涩噜噜噜网站| 欧美麻豆久久久久久中文| 日韩视频免费在线观看| 久久久久久久爱| 成人有码视频在线播放| 午夜欧美不卡精品aaaaa| 亚洲精品97久久| 在线观看日韩专区| 粉嫩老牛aⅴ一区二区三区| 国产精品成人av在线| 日韩69视频在线观看| 国产激情999| 91精品久久久久久久久久另类| 78m国产成人精品视频| 91精品国产乱码久久久久久久久| 日韩女在线观看| 亚洲欧美日韩中文在线| 国产精品亚洲欧美导航| 欧美老妇交乱视频| 亚洲激情 国产|