守护进程就是在后台运行且不与任何终端关联的进程
在网上看到一位仁兄总结的不错,摘抄如下:
守护进程的一般编写步骤:
- 脱离控制终端(父进程),使父进程为init
- 禁止进程重新打开控制终端
- 关闭文件描述符(从父进程继承了文件描述符,最好先进行关闭,避免不必要的系统资源的浪费)
- 更改工作目录(避免工作目录被卸载)
- 重设文件创建掩码(避免创建文件的时候权限和我们所需要权限不一致)
以下这篇文章讲的比较详细:
Linux进程间关系之守护进程
下面是nginx源码创建守护进程的函数
ngx_int_t
ngx_daemon(ngx_log_t *log)
{
int fd;
switch (fork()) {//此处是fork一个子进程,并且结束父进程,让新创建的进程由init进程接管,即init进程成为新创建进程的父进程
case -1:
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
return NGX_ERROR;
case 0:
break;//子进程继续往下运行
default:
exit(0);// 父进程立即结束
}
ngx_parent = ngx_pid;
ngx_pid = ngx_getpid();
if (setsid() == -1) {//此处是创建一个新会话,跟进程组有关
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
return NGX_ERROR;
}
umask(0);//此处清理文件的创建掩码
fd = open("/dev/null", O_RDWR);//打开一个/dev/null文件,任何写到这个文件的内容被直接丢弃
if (fd == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
"open(\"/dev/null\") failed");
return NGX_ERROR;
}
if (dup2(fd, STDIN_FILENO) == -1) {//将进程的标准输入重定向到/dev/null文件
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
return NGX_ERROR;
}
if (dup2(fd, STDOUT_FILENO) == -1) {//将进程的标准输出重定向到/dev/null文件
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
return NGX_ERROR;
}
#if 0
if (dup2(fd, STDERR_FILENO) == -1) {//将进程的标准错误输出重定向到/dev/null文件
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
return NGX_ERROR;
}
#endif
if (fd > STDERR_FILENO) {
if (close(fd) == -1) {//关闭/dev/null的文件描述符,此处不用担心标准输入,标准输出,标准错误输出写不到/dev/null,因为dup2函数实际上是新创建了一个描述符,跟现在关闭的fd描述符是两个独立的描述符
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
return NGX_ERROR;
}
}
return NGX_OK;
}