/** * 创建一个worker进程 * @param string $worker_name 服务名 * @return int 父进程:>0得到新worker的pid ;<0 出错; 子进程:始终为0 */ protected static function createOneWorker($worker_name) { // 创建子进程 $pid = pcntl_fork(); // 先处理收到的信号 pcntl_signal_dispatch(); // 父进程 if ($pid > 0) { // 初始化master的一些东东 self::$workerPidMap[$worker_name][$pid] = $pid; // 更新进程信息到共享内存 self::updateStatusToShm(); return $pid; } elseif ($pid === 0) { // 忽略信号 self::ignoreSignal(); // 清空任务 Lib\Task::delAll(); // 关闭不用的监听socket foreach (self::$listenedSocketsArray as $tmp_worker_name => $tmp_socket) { if ($tmp_worker_name != $worker_name) { fclose($tmp_socket); } } // 尝试以指定用户运行worker进程 if ($worker_user = Lib\Config::get($worker_name . '.user')) { self::setProcUser($worker_user); } // 关闭输出 self::resetStdFd(Lib\Config::get($worker_name . '.no_debug')); // 尝试设置子进程进程名称 self::setWorkerProcTitle($worker_name); // 包含必要文件 require_once WORKERMAN_ROOT_DIR . 'Core/SocketWorker.php'; // 查找worker文件 $worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file'); $class_name = basename($worker_file, '.php'); // 如果有语法错误 sleep 5秒 避免狂刷日志 if (\Man\Core\Lib\Checker::checkSyntaxError($worker_file, $class_name)) { sleep(5); } require_once $worker_file; // 创建实例 $worker = new $class_name($worker_name); // 如果该worker有配置监听端口,则将监听端口的socket传递给子进程 if (isset(self::$listenedSocketsArray[$worker_name])) { $worker->setListendSocket(self::$listenedSocketsArray[$worker_name]); } // 使worker开始服务 $worker->start(); return 0; } else { self::notice("create worker fail worker_name:{$worker_name} detail:pcntl_fork fail"); return $pid; } }
/** * 创建一个worker进程 * @param string $worker_name worker的名称 * @return int 父进程:>0得到新worker的pid ;<0 出错; 子进程:始终为0 */ protected static function forkOneWorker($worker_name) { // 创建子进程 $pid = pcntl_fork(); // 先处理收到的信号 pcntl_signal_dispatch(); // 父进程 if ($pid > 0) { // 初始化master的一些东东 self::$workerPids[$worker_name][$pid] = $pid; // 更新进程信息到共享内存 self::updateStatusToShm(); return $pid; } elseif ($pid === 0) { // 忽略信号 self::ignoreSignal(); // 清空任务 Lib\Task::delAll(); // 关闭不用的监听socket foreach (self::$listenedSockets as $tmp_worker_name => $tmp_socket) { if ($tmp_worker_name != $worker_name) { fclose($tmp_socket); } } // 尝试以指定用户运行worker if ($worker_user = Lib\Config::get($worker_name . '.user')) { self::setWorkerUser($worker_user); } // 关闭输出 self::resetStdFd(); // 尝试设置子进程进程名称 self::setWorkerProcessTitle($worker_name); // 查找worker文件 if ($worker_file = \Man\Core\Lib\Config::get($worker_name . '.worker_file')) { include_once $worker_file; $class_name = basename($worker_file, '.php'); } else { $class_name = $worker_name; include_once WORKERMAN_ROOT_DIR . "workers/{$worker_name}.php"; } // 创建实例 $worker = new $class_name($worker_name); // 如果该worker有配置监听端口,则将监听端口的socket传递给子进程 if (isset(self::$listenedSockets[$worker_name])) { $worker->setListendSocket(self::$listenedSockets[$worker_name]); } // 使worker开始服务 $worker->start(); return 0; } else { self::notice("create worker fail worker_name:{$worker_name} detail:pcntl_fork fail"); return $pid; } }