swoole_process提供的daemon用于使当前进程蜕变为一个守护进程。
//低于1.9.1的版本
bool swoole_process::daemon(bool $nochdir = false, bool $noclose = false);
//1.9.1或更高版本
bool swoole_process::daemon(bool $nochdir = true, bool $noclose = true);
- $nochdir,为true表示不要切换当前目录到根目录。
- $noclose,为true表示不要关闭标准输入输出文件描述符。
下面我们分析下其流程。
static PHP_METHOD(swoole_process, daemon)
{
zend_bool nochdir = 1;
zend_bool noclose = 1;
//解析输入参数信息,这两个参数具体的含义请参考上面php接口描述
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|bb", &nochdir, &noclose) == FAILURE)
{
RETURN_FALSE;
}
//调用daemon函数,同时返回其处理结果
RETURN_BOOL(daemon(nochdir, noclose) == 0);
}
int daemon(int nochdir, int noclose)
{
pid_t pid;
if (!nochdir && chdir("/") != 0)//未设置不切换根目录,切换到根目录失败
{
swWarn("chdir() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
if (!noclose)//要关闭描述符
{
int fd = open("/dev/null", O_RDWR);//打开/dev/null文件
if (fd < 0)
{
swWarn("open() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
if (dup2(fd, 0) < 0 || dup2(fd, 1) < 0 || dup2(fd, 2) < 0)//将标准输入、错误、输出重定向到fd中
{
close(fd);
swWarn("dup2() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
close(fd);//关闭文件描述符
}
pid = fork();//fork进程
if (pid < 0)//fork失败
{
swWarn("fork() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
if (pid > 0)//父进程
{
_exit(0);//中断父进程
}
if (setsid() < 0)//子进程,脱离控制终端
{
swWarn("setsid() failed. Error: %s[%d]", strerror(errno), errno);
return -1;
}
return 0;
}