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

在ngx_spawn_process函数中,有句:ngx_channel = ngx_processes[s].channel[1],我们知道s是本次用来放置新创建进程信息的(在ngx_processes中)位置,即也是ngx_process_slot变量,因为这两个变量,ngx_channel和ngx_process_slot是在fork之前设置的,那么在随后子进程的init时,就会用到这两个刚刚在父进程中设置的值,ngx_add_channel_event中的ngx_channel就是当前子进程的channle[1],所以这里的意图也就明了了,该worker进程就是通过监听channel[1]的读事件来获取信息。好了,然后我们搜遍所有代码,并没有看到在某个channel上监听写事件的动作,那么我们要问了,子进程有没有需要写一些数据的时候呢?好吧,我们全文搜索"channel[0]",看看会发现什么。我想你肯定发现了ngx_write_channel函数,它的作用就是往channel[0]中去写数据,那么是都是谁在写呢?

我们找到了ngx_pass_open_channel,也就是我上文所说的“广播”。你要知道的一点就是,父进程中通过向channle[0]里写数据,可以在子进程中相应的channel[1]中读取。好了到这里我们前面提到的一些疑问基本上都有了答案,父进程通过向各个channel[0]中“广播”数据,子进程在其自己的channel[1]中读取相应的数据,他们正是通过这种方式来通信的。那么nginx进程间通信的机制仅仅就是这些吗?远不止。。。

我们前面提到父进程写channel[0],子进程读channel[1],那么父进程都传了些啥?我们最容易看到的载体是ngx_channel_t结构,在ngx_pass_open_channel中,参数ch就是这样的一个结构:

/*   * command传递的命令   * pid本次产生的新进程pid   * slot新进程在ngx_processes数组中的位置   * fd新进程中channel[0]   */   typedef struct {        ngx_uint_t  command;        ngx_pid_t   pid;        ngx_int_t   slot;        ngx_fd_t    fd;   } ngx_channel_t;  

对于command,在当前为NGX_CMD_OPEN_CHANNEL,也就是告诉其他的子进程,“某个新的进程刚刚诞生,注意同步相关信息”。那么子进程得到这个信息会怎么做呢?

还记得这个ngx_channel_handler函数吗,在注册读事件时设置的,它里面会调用ngx_read_channel来或者这个channel数据。如果发现是NGX_CMD_OPEN_CHANNEL命令,那么就在ngx_processes的相应位置上更新新诞生进程的信息:

ngx_processes[ch.slot].pid = ch.pid;

ngx_processes[ch.slot].channel[0] = ch.fd;

这个NGX_CMD_OPEN_CHANNEL算是最简单的命令了,其他的处理有什么特别的地方?

以上我们讨论的这些算是基础设施了,在这之上,nginx做了很多的好东西。目前看到的只是在nginx初始化时做的事情,那么在实际运行中,进程间又有哪些交互和通信呢?后面的文章讨论。

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

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