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

多进程你可能很熟悉,也许有一套自己的使用习惯和方法。这东西没有什么权威建议,书上只是给出了基本知识点,至于具体怎么去用,因人而异。nginx在多进程设计方面有很多值得学习和借鉴的东西,我认为是一套比较好的实现方案。你也许认为这东西很简单,是老生常谈的东西了,但是我这里要提醒你一下,俗话道酒是陈的香,越经典的东西越值得去琢磨,不要对自己太自信。善于思考的家伙总是会在一些老的技术上给你许多新鲜的见解,这种牛人你不会没遇到过吧!扯淡罢了,回到正题。

看函数ngx_spawn_process的骨架:

for (s = 0; s < ngx_last_process; s++) {      ...   }         ...         /*   * 实现异步通知的两个步骤,在nginx事件模型的rtsig机制中会用到    * 参考:   */   if (ioctl(ngx_processes[s].channel[0], FIOASYNC, &on) == -1) {       ...   }   if (fcntl(ngx_processes[s].channel[0], F_SETOWN, ngx_pid) == -1) {       ...   }         ...         ngx_channel = ngx_processes[s].channel[1];         ...         // 当前产生的子进程在ngx_processes数组中的下标    ngx_process_slot = s;         /*   * 在fork之后,父进程的ngx_processes数组,“传递”给了子进程,但是这时子进程拿到的数组是截至创建该进程之前其他进程的信息。   * 由于子进程是父进程fork得到的,那么在之后父进程的操作结果在子进程中就不可见了。假设当前诞生的是进程1,用p1表示,当父进程   * 创建p5时,那么p2-p5的进程信息在p1中是缺失的,那么p1需要这些信息吗?如果需要的话,该通过什么手段给它呢?   * 见ngx_start_worker_processes相关分析   */   ngx_pid = fork();   switch (pid) {       ...       case 0:           ngx_pid = ngx_getpid();           proc(cycle, data);           break;          default:           break;       }         ...         ngx_processes[s].pid = pid;         ...         if (s == ngx_last_process) {        ngx_last_process++;   }         /*   * 父进程,也就是master进程,依次创建work子进程,为了确保ngx_processes数组在子进程间同步,每次创建完一个子进程,   * 就通过ngx_pass_open_channel,做一次广播,告诉先前已经创建的子进程: "新进程诞生,注意更新进程数组相关项"   * 那么这些子进程又是如何更新这些信息的呢?答案在ngx_worker_process_init中。  */   ngx_start_worker_processes(ngx_cycle_t *cycle, ngx_int_t n, ngx_int_t type)   {       ngx_int_t      i;       ngx_channel_t  ch;          ch.command = NGX_CMD_OPEN_CHANNEL;          for (i = 0; i < n; i++) {              ch.pid = ngx_processes[ngx_process_slot].pid;           ch.slot = ngx_process_slot;           ch.fd = ngx_processes[ngx_process_slot].channel[0];              ngx_pass_open_channel(cycle, &ch);       }   }  

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/07638404d74f7ff015ac05a523d87ca0.html