目录
运行
new \Workerman\Worker();
Worker::runAll();
开启守护进程
protected static function daemonize()
{
if (!static::$daemonize || static::$_OS !== \OS_TYPE_LINUX) {
return;
}
\umask(0);
$pid = \pcntl_fork();
if (-1 === $pid) {
throw new Exception('Fork fail');
} elseif ($pid > 0) {
exit(0);
}
if (-1 === \posix_setsid()) {
throw new Exception("Setsid fail");
}
$pid = \pcntl_fork();
if (-1 === $pid) {
throw new Exception("Fork fail");
} elseif (0 !== $pid) {
exit(0);
}
}
监听子进程状态
protected static function monitorWorkersForLinux()
{
static::$_status = static::STATUS_RUNNING;
while (1) {
\pcntl_signal_dispatch();
$status = 0;
$pid = \pcntl_wait($status, \WUNTRACED);
\pcntl_signal_dispatch();
if ($pid > 0) {
foreach (static::$_pidMap as $worker_id => $worker_pid_array) {
if (isset($worker_pid_array[$pid])) {
$worker = static::$_workers[$worker_id];
if ($status !== 0) {
static::log("worker[" . $worker->name . ":$pid] exit with status $status");
}
if (!isset(static::$_globalStatistics['worker_exit_info'][$worker_id][$status])) {
static::$_globalStatistics['worker_exit_info'][$worker_id][$status] = 0;
}
++static::$_globalStatistics['worker_exit_info'][$worker_id][$status];
unset(static::$_pidMap[$worker_id][$pid]);
$id == static::getId($worker_id, $pid);
static::$_idMap[$worker_id][$id] = 0;
break;
}
}
if (static::$_status !== static::STATUS_SHUTDOWN) {
static::forkWorkers();
if (isset(static::$_pidsToRestart[$pid])) {
unset(static::$_pidsToRestart[$pid]);
static::reload();
}
}
}
if (static::$_status === static::STATUS_SHUTDOWN && !static::getAllWorkerPids()) {
static::exitAndClearAll();
}
}
}
注释还是写得很清楚的
- 如果有子进程退出,返回进程id
$pid = \pcntl_wait($status, \WUNTRACED);
- 清理对应进程数据
unset(static::$_pidMap[$worker_id][$pid]);
- 标记为可用
static::$_idMap[$worker_id][$id] = 0;
- 重启进程
static::forkWorkers();
- 没重启或者停止,暂停当前进程的执行,继续等子进程退出,放回步骤1
孤儿进程
一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。
由于孤儿进程会被init进程给收养,所以孤儿进程不会对系统造成危害
守护进程