`
zzc1684
  • 浏览: 1233372 次
  • 性别: Icon_minigender_1
  • 来自: 广州
文章分类
社区版块
存档分类
最新评论

Nginx父子进程的创建及主体工作函数

阅读更多

根据Nginx(0.7.67版本)的代码,对Nginx基本的进程创建,进程主体以及事件处理进行了简要的分析。

 
基本上,父进程(即主进程)一开始会初始化及读取配置,并加载各模块的功能,然后fork()出N个子进程(即工作进程),具有相同的工作逻辑 和功能。父进程负责监听信号(如HUP,QUIT等),通过socket pair把信号传递给子进程(子进程间一般不通信)。子进程通过事件来处理父进程传递的信号。因为每个子进程都共享服务监听端口(如http 80),当用户发送请求时,会触发子进程的事件调用函数。因此在accept()请求的时候,需要用到mutex,保证只有一个工作进程接受并处理请求。
 
Nginx主进程的入口是跟一般的程序一样的main()函数,它的代码是这样的:
C代码  收藏代码
  1. int ngx_cdecl main(int argc, char *const *argv)  
  2. {  
  3.     /*...*/  
  4.   
  5.     //nginx 启动的时候会尝试从环境变量中读取前次执行时候的监听套接口的id,  
  6.     //并会创建对应数量的ngx_listening_t结构变量(存于 cycle->listening数组中),  
  7.     //然后调用这个接口通过getsockname,getsockopt等系统调用把原来套接口的属性信息和  
  8.     //设置参数读取出来去设置那些新创建的ngx_listening_t结构变量,这样就继承了前次执行  
  9.     //时候的监听套接口了,这个接口是在 ngx_init_cycle之前调用的  
  10.   
  11.     if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) {   
  12.         return 1;                                 
  13.     }  
  14.   
  15.     /*...*/  
  16.   
  17.     //ngx_modules数组在objs/ngx_modules.c定义  
  18.     ngx_max_module = 0;  
  19.     for (i = 0; ngx_modules[i]; i++) {  
  20.         ngx_modules[i]->index = ngx_max_module++; //将每个模块编号  
  21.     }  
  22.   
  23.     //ngx_init_cycle()函数,这是个比较重要的函数,被main, ngx_master_process_cycle  
  24.     //和ngx_single_process_cycle 调用, 其中后两者是在reconfigure的时候被调用的。  
  25.     //它主要工作是,初始化cycle是基于旧有的cycle进行的; 会继承old cycle的很多属性,   
  26.     //比如log等, 但是同时会对很多资源重新分配, 比如pool, shared mem, file handler,   
  27.     //bind/listen socket等,同时清除旧有的cycle的资源  
  28.     //读取配置文件也是在这里完成的  
  29.     cycle = ngx_init_cycle(&init_cycle);   
  30.   
  31.     if (ngx_process == NGX_PROCESS_SINGLE) {  
  32.         ngx_single_process_cycle(cycle);  
  33.     }   
  34.     else {    
  35.         //一般采用多进程处理请求  
  36.         ngx_master_process_cycle(cycle);  
  37.     }  
  38. }  
 
 
 
C代码  收藏代码
  1. //ngx_start_worker_processes()函数,这个函数按指定数目n,以ngx_worker_process_cycle()函  
  2. //数为参数调用ngx_spawn_process()创建work进程并初始化相关资源和属性;  
  3. //执行子进程的执行函数ngx_worker_process_cycle;向之前已经创建的所有worker广播当前创建的  
  4. //worker进程的信息;每个进程打开一个通道(ngx_pass_open_channel())  
  5. //n是worker process的数目  
  6. //type 即创建新进程式的方式,如NGX_PROCESS_RESPAWN, NGX_PROCESS_JUST_RESPAWN  
  7. static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)  
  8. {  
  9.     ngx_int_t      i;  
  10.     ngx_channel_t  ch;  
  11.   
  12.     ch.command = NGX_CMD_OPEN_CHANNEL;  
  13.   
  14.     for (i = 0; i < n; i++) {  
  15.         //从config读取CPU的分配  
  16.         cpu_affinity = ngx_get_cpu_affinity(i);  
  17.         //ngx_spawn_process中设置ngx_process_slot为被分配到子进程的  
  18.         //空闲slot  
  19.         ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,  
  20.                     "worker process", type);  
  21.           
  22.         ch.pid = ngx_processes[ngx_process_slot].pid;  
  23.         ch.slot = ngx_process_slot;  
  24.         ch.fd = ngx_processes[ngx_process_slot].channel[0];  
  25.         //ngx_pass_open_channel 把这个worker的channel[0]和进程id  
  26.         //在进程表中的偏移slot广播(ngx_write_channel())给所有其他已经  
  27.         //创建的worker。  
  28.         //这样,创建完所有进程之后,每个worker就获得了所有其他worker的  
  29.         //channel[0]了  
  30.         ngx_pass_open_channel(cycle, &ch);  
  31.     }  
  32. }  
 
 
 
C代码  收藏代码
  1. ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data, char *name, ngx_int_t respawn)  
  2. {  
  3.     /*...*/  
  4.     //如果类型为NGX_PROCESS_DETACHED,则说明是热代码替换(热代码替换也是通过这  
  5.     //个函数进行处理的),因此不需要新建socketpair。   
  6.     if (respawn != NGX_PROCESS_DETACHED) {  
  7.         //建立socketpair    
  8.         //创建socketpair用于进程间通信,master进程为每个worker创建一对  
  9.         //socket, master进程空间打开所有socketpair的channel[0],  
  10.         //channel[1]两端句柄。   
  11.         //当创建一个worker的时候,这个worker会继承master当前已经创建并  
  12.         //打开的所有socketpair。  
  13.         //这个worker初始化的时候(调用ngx_worker_process_init)会关闭  
  14.         //本进程对应socketpair的channel[0]和其他worker对应的  
  15.         //channel[1],保持打开本进程对应socketpair的channel[1]和其他  
  16.         //worker对应的channel[0],并监听本进程对应socketpair的  
  17.         //channel[1]的可读事件。这样,每个worker就拥有了其他worker的  
  18.         //channel[0],可以sendmsg(channel[0], ...)向其他worker发送消息          
  19.         /*...*/   
  20.     }  
  21.   
  22.     /*...*/  
  23.     //创建子进程  
  24.     pid = fork();  
  25.     switch (pid) {  
  26.         case -1:  
  27.             ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,   
  28.                 "fork() failed while spawning "%s"", name);  
  29.             ngx_close_channel(ngx_processes[s].channel, cycle->log);  
  30.             return NGX_INVALID_PID;  
  31.         //在子进程里,执行传递进来的子进程的函数   
  32.         case 0:  
  33.             ngx_pid = ngx_getpid();  
  34.             //调用ngx_worker_process_cycle()  
  35.             //注意:这个函数中定义了子进程处理事件的循环,即子进程不会  
  36.             //执行这个函数之后的语句  
  37.             proc(cycle, data);  
  38.             break;  
  39.         default:  
  40.             break;  
  41.     }  
  42. }  
 
 
C代码  收藏代码
  1. //worker进程的主体  
  2. static void ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)  
  3. {  
  4.     //设置一些环境变量  
  5.     //调用所有模块的init_process钩子函数  
  6.     //将其他进程的channel[1]关闭,自己的除外  
  7.     //子进程继承了父进程的ngx_processes数组,但子进程只监听自己的channel[1]  
  8.     //将自己的channel[0]关闭  
  9.     //因为自己的channel[0]是给其他子进程,用来发送消息的sendmsg  
  10.     //调用ngx_add_channel_event()函数,给ngx_channel注册一个读事件处理函数。  
  11.     ngx_worker_process_init(cycle, 1);  
  12.     //主循环,处理事件  
  13.     for ( ;; ) {  
  14.           
  15.         /*...*/  
  16.   
  17.         //调用epoll,周期性监听事件  
  18.         //先接收连接(并不处理事件),以及处理进程间信号(如有)  
  19.         //处理accept queue和event queue里面的事件  
  20.         ngx_process_events_and_timers(cycle);  
  21.   
  22.         /*...*/  
  23.     }  
  24.   
  25.     /*...*/  
  26. }  
 
分享到:
评论

相关推荐

    nginx将进程注册为Windows服务

    2. **创建配置文件**:创建一个XML文件(如`nginx-service.xml`),配置Nginx服务的相关参数。示例如下: ```xml &lt;id&gt;nginx &lt;name&gt;Nginx Server &lt;description&gt;Nginx ...

    keepalived监控nginx进程

    Keepalived 监控 Nginx 进程操作手册 Keepalived 是一个基于 VRRP 协议的高可用性解决方案,旨在提供高可用性的负载均衡解决方案。本操作手册主要介绍如何使用 Keepalived 监控 Nginx 进程,实现系统的负载均衡。 ...

    结束所有nginx进程-一键干死nginx

    可以查出系统中所有nginx进程,直接kill进程,一键搞定他,

    Nginx-ngx_lua模块原理和内置函数.docx

    - 每个 Nginx worker 进程都会创建一个 Lua 虚拟机 (LuaVM),该 VM 在整个 worker 的生命周期内都是共享的。 - 这种设计可以减少每次请求时创建和销毁虚拟机的开销,提高性能。 2. **Nginx I/O 原语封装:** - ...

    重启或杀掉Nginx进程后丢失nginx.pid的解决办法

    安装SSL证书时,强行杀掉了Nginx的进程,就再也没起来: Restarting nginx daemon: nginxcat: /usr/local/nginx/logs/nginx.pid: No such file or directorykill: usage: kill [-s sigspec | -n signum | -sigspec] ...

    nginx进程文件

    linux下设置nginx为系统进程,进行快速的stop+start+restart操作。

    从nginx角度看服务器多进程模型设计

    总结来说,从Nginx的角度看服务器多进程模型设计,我们能学到如何通过主工作进程结构实现高效的并发处理,理解非阻塞I/O和共享内存通信在提升性能中的作用,以及如何利用多进程来确保服务的稳定性和资源隔离。...

    Nginx 启动、停止、重启、升级操作命令收集

    停止操作 停止操作是通过向nginx进程发送信号(什么是信号请参阅linux文章)来进行的 步骤1:查询nginx主进程号 ps -ef | grep nginx 在进程列表里面找master进程,它的编号就是主进程号了。 步骤2:发送信号 从容...

    Centos7环境下Nginx版本升级方式及步骤

    发送HUP信号给主进程,它会创建新的worker并逐步关闭旧的,实现平滑升级。 2. **查看当前版本和编译参数**:使用`nginx -V`查看当前版本和编译参数。 3. **下载源码**:从Nginx官网`http://nginx.org/download/`下载...

    Nginx常见错误及解决方法.doc

    Nginx 常见错误及解决方法 Nginx 是一个流行的开源 Web 服务器软件,然而在实际使用中经常会遇到各种错误,影响服务器的稳定运行。下面将介绍 Nginx 中的一些常见错误及解决方法。 一、Nginx 启动错误 在安装 ...

    Nginx笔记-Nginx中进程结构及使用Linux信号量管理

    Nginx:一个进程处理多个请求,非阻塞式; Nginx的应用场景 Nginx只能处理静态资源,动态资源还得反向代理到应用服务器上。 下面是Nginx处理请求的过程: Nginx有点及特点 热部署、平滑升级、开源及二次开发、高...

    nginx-1.20.2.tar.gz

    Nginx 采用主进程(master process)+ 工作进程(worker processes)的模型运行。主进程负责读取和解析配置文件,然后创建并管理多个工作进程。工作进程则负责实际的网络I/O和请求处理。 ### 六、Nginx 运维 在...

    基于CentOS6.8镜像+OpenSSL1.1.1g通过Nginx1.14离线创建HTTPS服务

    在DockerOS6.8的镜像里,离线安装Nginx及配置...7、创建证书并修改Nginx配置后从新载入配置文件; 8、验证https服务和http自动跳转。 镜像下载地址: https://hub.docker.com/repository/docker/estc/centos4https

    借鉴nginx特性应用于其他项目-Nginx多进程高并发、低时延、高可靠机制在缓存代理中的应用1

    Worker 进程模型详解在 Nginx 的设计中,Master 进程主要负责接收来自客户端的连接请求,然后将这些请求分发给 Worker 进程处理。Master 进程不直接处理请求,而是通过事件驱动模型(epoll)来监控 Worker 进程的...

    nginx核心详解

    在Nginx的启动过程中,主进程通过`ngx_master_process_cycle()`函数来执行初始化任务,然后调用`ngx_start_worker_processes()`来创建并启动工作进程。工作进程的数量通常在配置文件中设定,可以根据服务器的负载...

    nginx worker进程循环的实现

    这个函数会创建指定数量的Worker进程,并为每个进程设置与Master进程通信的Socket。在创建Worker进程时,会通过`fork()`系统调用复制Master的上下文,包括Socket对。 Worker进程的事件循环主要是通过`ngx_event_...

    Nginx面试专题及答案.pdf

    Nginx使用的是反应器模式,其工作原理是通过主事件循环等待操作系统发出准备事件的信号,从而读取数据到缓冲区进行处理,单个线程能够处理数万个并发连接。 在配置文件中,若想阻止处理请求,可以设置server_name为...

    NGINX开发从入门到精通

    worker进程是NGINX的工作进程,负责处理基本的网络事件。worker进程之间是平等的,每个进程都有可能处理来自客户端的请求。worker进程的个数可以设置,通常设置与机器CPU核数一致。 NGINX的多进程模式 NGINX采用的...

    nginx源代码剖析

    Nginx采用经典的master-worker架构,主进程(master process)负责管理多个工作进程(worker processes)。主进程主要进行全局初始化和工作进程的监控与调度,而实际的HTTP请求处理则由工作进程完成。工作进程之间...

    Nginx 配置文件 nginx.conf 详解

    工作进程是 Nginx 服务器的核心组件,它负责处理客户端的请求。我们可以通过 `worker_processes` 指令来设置工作进程的数量,例如 `worker_processes 1;`,这将设置 Nginx 服务器只有一个工作进程。 错误日志 错误...

Global site tag (gtag.js) - Google Analytics