nginx创建n个工作子进程

nginx创建n个工作子进程

nginx属于多进程方案,那么是怎么创建n个进程的呢??

1.1 linux中fork创建进程

linux下创建进程的系统调用是fork。其定义如下
#include <sys/types.h>
#include <unistd.h>
pid_t fork();
在循环中创建进程时,进程的个数是怎样的?
1、循环中没有任何父子进程的判断

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
    
    
    pid_t pid;
    int idx = -1;
    for (int i = 0; i < 2; i++) {
    
    
        pid = fork();  
    }
    while (1);    
    exit(0) ;
}

输出为
在这里插入图片描述
可以看出总共有4个进程
其生成过程图如下所示
在这里插入图片描述
2、创建指定个数的子进程

在创建子进程后,根据fork的返回值判断是否是子进程,如果是子进程:
(1)退出循环,进入子进程的事件处理;(2)不退出循环,直接是子进程的事件处理,其中 事件处理是一个循环,所在循环退出前,子进程是不会执行for语句的,这也是nginx创建工作进程的方式
代码如下

int main()
{
    
    
    pid_t pid;
    int idx = -1;
    for (int i = 0; i < 2; i++) {
    
    
        pid = fork();
        if (pid < 0) {
    
    
            exit(-1);
        } else if (pid > 0) {
    
    
            continue;
        } else {
    
    
            idx = i;
            while (1) {
    
    
                printf("idx=%d\n", idx);
            }
        }
    }
    while (1);    
    exit(0) ;
}

输出为
在这里插入图片描述
可以看到有3个进程,两个子进程,一个父进程

其生成过程图如下所示

在这里插入图片描述

2.nginx中创建n个进程

nginx创建work进程是在一个循环中进行的;


static void ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)
{
    
    

    for (i = 0; i < n; i++) {
    
    
        //省略
        ngx_spawn_process(cycle, ngx_worker_process_cycle, NULL,
                          "worker process", type);
      //省略若干
    }
}

ngx_pid_t ngx_spawn_process(ngx_cycle_t *cycle, ngx_spawn_proc_pt proc, void *data,
    char *name, ngx_int_t respawn)
{
    
    
    //省略若干
    pid = fork();
   switch (pid) {
    
    
    case -1:
          //省略若干
    case 0:
        ngx_pid = ngx_getpid();
        proc(cycle, data);
        break;
    default:
        break;
    }
   //省略若干
}

我们知道,fork在循环中创建子进程的个数是与循环个数n不等的,例如:

forint i = 0; i < 3; ++i)

{
    
    
       pid = fork();
      if(pid > 0)
      {
    
    
            //父进程
      }
      else if(pid == 0)
      {
    
    
           //子进程
      }
      else
      {
    
    
            //error
      }
}

上面的代码运行后,总共的进程数为2的3次方个,即8个进程;
那么问题来了,nginx也是通过for来创建work进程,如何控制work进程数目的呢?一值比较疑惑,通过仔细检查代码,发现原因这样的;

nginx在fork后,会运行  proc(cycle, data);  proc就是ngx_worker_process_cycle函数;
static void
ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
{
    
    
  
    for ( ;; ) {
    
    
                //省略若干
                ngx_worker_process_exit(cycle);          
              //省略若干
    }
}

在这个函数中,如果退出,最终会调用ngx_worker_process_exit(cycle);

static void
ngx_worker_process_exit(ngx_cycle_t *cycle)
 {
    
    
    //省略若干

    exit(0;

}

看到没有,这个函数最后会调用exit(0); 直接退出进程;所以整个过程明了了;

总结:
nginx通过fork循环来创建进程,是如何控制work进程数目,而没有出现进程泛滥,达到2的n次方的进程数目呢?
原因:在fork完work进程后,调用work进程的死循环函数,在死循环中,如果收到quit命令,会直接exit(),不会在work进程中再次执行fork函数,所以子进程不会在创建子进程。

参考资料:

  1. https://blog.csdn.net/xiexingshishu/article/details/46398051
  2. https://blog.csdn.net/sohu_2011/article/details/62045496

猜你喜欢

转载自blog.csdn.net/alpha_love/article/details/113826332