nginx代码学习_第一章守护进程
2016-08-03 16:34
176 查看
最近在学习linux的一些开源代码,nginx是我想要学习的第一个目标,因为它十分小巧相对于它的强大功能来说.
我使用过http服务端,文件目录浏览.除此之外我知道的还有反向代理,负载均衡,等功能.最主要的还是他代码量比较少,和我以前使用的项目结构相似有着一定的亲切感.
我主要想了解的几个主要功能模块包括:内存池,守护进程变化,以及http业务解析等,今天先看到了守护进程的代码比较少,先来了解这块代码.
二话不说上代码
ngx_int_t ngx_daemon(ngx_log_t *log)
{
int fd;
switch (fork()) {
case -1:
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
return NGX_ERROR;
case 0: //子进程作为守护进程
break;
default:
exit(0); //父进程退出
}
ngx_pid = ngx_getpid();
if (setsid() == -1) { //setsid创建一个新会话
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
return NGX_ERROR;
}
umask(0);
//打开文件/dev/null,使得其拥有守护进程的0,1,2。这样防止守护进程在终端设备上显示输出
fd = open("/dev/null", O_RDWR);
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) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
return NGX_ERROR;
}
if (dup2(fd, STDOUT_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
return NGX_ERROR;
}
#if 0
if (dup2(fd, STDERR_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
return NGX_ERROR;
}
#endif
if (fd > STDERR_FILENO) {
if (close(fd) == -1) { //关闭不需要的文件描述符
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
return NGX_ERROR;
}
}
return NGX_OK;
}
在这段代码里面一开始的frok函数很好理解,创建子进程将会作为守护进程使用,接下里是使用一个switch进行父进程退出.使子进程成为孤儿进程,接着子进程调用setsid创建新的会话,保证在登录会话断掉之后,进程能够一直存在.
在这块有个细节,就是如果是以库的形式提供这个函数的话,为了保险起见一般来说会去frok两次.原因是因为作为库函数的代码不知道接下来的代码会不会有ioctl(TIOCSCTTY)这种调用,如果有的话那么子进程就有当前的session,这时候调用setsid()是不会成功的,所以说这时候就算创建守护进程失败了,但是由于是编写的一整个程序,所以不会有上面之类的调用.
接下来脱离原进程文件权限使用umask,进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除.
然后将三个默认fd重定向到/dev/null上,分别为标准输入,标准输出,错误输出.
这样nginx的守护进程就写完了.但是这个不完全是一个完整的daemon的写法,一个完整的daemon的写法里面还会包括chdir('/'),切换工作目录,防止卸载.
我使用过http服务端,文件目录浏览.除此之外我知道的还有反向代理,负载均衡,等功能.最主要的还是他代码量比较少,和我以前使用的项目结构相似有着一定的亲切感.
我主要想了解的几个主要功能模块包括:内存池,守护进程变化,以及http业务解析等,今天先看到了守护进程的代码比较少,先来了解这块代码.
二话不说上代码
ngx_int_t ngx_daemon(ngx_log_t *log)
{
int fd;
switch (fork()) {
case -1:
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "fork() failed");
return NGX_ERROR;
case 0: //子进程作为守护进程
break;
default:
exit(0); //父进程退出
}
ngx_pid = ngx_getpid();
if (setsid() == -1) { //setsid创建一个新会话
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "setsid() failed");
return NGX_ERROR;
}
umask(0);
//打开文件/dev/null,使得其拥有守护进程的0,1,2。这样防止守护进程在终端设备上显示输出
fd = open("/dev/null", O_RDWR);
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) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDIN) failed");
return NGX_ERROR;
}
if (dup2(fd, STDOUT_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDOUT) failed");
return NGX_ERROR;
}
#if 0
if (dup2(fd, STDERR_FILENO) == -1) {
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed");
return NGX_ERROR;
}
#endif
if (fd > STDERR_FILENO) {
if (close(fd) == -1) { //关闭不需要的文件描述符
ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "close() failed");
return NGX_ERROR;
}
}
return NGX_OK;
}
在这段代码里面一开始的frok函数很好理解,创建子进程将会作为守护进程使用,接下里是使用一个switch进行父进程退出.使子进程成为孤儿进程,接着子进程调用setsid创建新的会话,保证在登录会话断掉之后,进程能够一直存在.
在这块有个细节,就是如果是以库的形式提供这个函数的话,为了保险起见一般来说会去frok两次.原因是因为作为库函数的代码不知道接下来的代码会不会有ioctl(TIOCSCTTY)这种调用,如果有的话那么子进程就有当前的session,这时候调用setsid()是不会成功的,所以说这时候就算创建守护进程失败了,但是由于是编写的一整个程序,所以不会有上面之类的调用.
接下来脱离原进程文件权限使用umask,进程从创建它的父进程那里继承了文件创建掩模。它可能修改守护进程所创建的文件的存取位。为防止这一点,将文件创建掩模清除.
然后将三个默认fd重定向到/dev/null上,分别为标准输入,标准输出,错误输出.
这样nginx的守护进程就写完了.但是这个不完全是一个完整的daemon的写法,一个完整的daemon的写法里面还会包括chdir('/'),切换工作目录,防止卸载.
相关文章推荐
- nginx学习十三 初始fork和nginx守护进程ngx_daemon
- Nginx学习笔记——进程代码片段(一)
- linux下daemon守护进程的实现(以nginx代码为例)
- linux下daemon守护进程的实现(以nginx代码为例)
- nginx的守护进程学习
- nginx 源码学习笔记(十六)—— ngx_start_worker_processes子进程创建
- nginx 源码学习笔记(十七)—— ngx_worker_process_cycle子进程执行
- linux下创建守护进程(daemon process)代码-详细注释
- 用perl实现守护进程(daemon)代码
- linux学习笔记:关于linux守护进程与终端的通信
- linux学习 - 守护进程
- nginx 源码学习笔记(十六)—— ngx_start_worker_processes子进程创建
- UNIX环境高级编程学习之第十三章守护进程 - 单实例的守护进程
- nginx代码分析--进程和模块初始化
- NGINX(1.3.7)代码学习: 动态数组
- NGINX(1.3.7)代码学习:内存池
- nginx 源码学习笔记(十七)—— ngx_worker_process_cycle子进程执行
- linux下创建守护进程(daemon process)代码-详细注释
- UNIX环境高级编程学习之第十三章守护进程 - 初始化一个守护进程
- nginx多进程模型之热代码平滑升级