/** * 创建一个子进程 * @param Worker $worker * @throws Exception */ public function fork_one_task($taskid) { $pid = pcntl_fork(); // 主进程记录子进程pid if ($pid > 0) { // 暂时没用 self::$taskpids[$taskid] = $pid; } elseif (0 === $pid) { log::warn("Fork children task({$taskid}) successful...\n"); self::$time_start = microtime(true); self::$taskid = $taskid; self::$taskpid = posix_getpid(); self::$taskmaster = false; self::$collect_succ = 0; self::$collect_fail = 0; while ($this->queue_lsize()) { // 如果队列中的网页比任务数多,子任务可以采集 if ($this->queue_lsize() > self::$tasknum * 2) { // 抓取页面 $this->collect_page(); } else { log::warn("Task(" . self::$taskid . ") waiting...\n"); sleep(1); } // 每采集成功一个页面,生成当前进程状态到文件,供主进程使用 $mem = round(memory_get_usage(true) / (1024 * 1024), 2) . "MB"; $use_time = microtime(true) - self::$time_start; $speed = round((self::$collect_succ + self::$collect_fail) / $use_time, 2) . "/s"; $status = array('id' => self::$taskid, 'pid' => self::$taskpid, 'mem' => $mem, 'collect_succ' => self::$collect_succ, 'collect_fail' => self::$collect_fail, 'speed' => $speed); util::put_file(PATH_DATA . "/status/" . self::$taskid, json_encode($status)); } // 这里用0表示正常退出 exit(0); } else { log::error("Fork children task({$i}) fail...\n"); exit; } }