风信子·重瓣——nginx进程间通讯
文/孙富玲
当nginx服务器使用多进程模式时,进程间需要进行频繁的通信,尤其是主进程和工作进程之间,主进程需要向子进程发送控制命令,还要能够方便地取子进程的运行状态,同时,各个工作进程之间也是有交互的。进程问必須要实现一个高效稳定的双向通信渠道。
Linux平台上进程问通信的方式有很多, 经典的解决方案包括以下几种:
使用IPC(包括消息队列、信号量、共享存储)、管道、套接字socket这三种方式中,IPC虽然功能很强大,但是不支持Nginx服务器使用的事件驱动模型。管道简单易用,但是限制也比较多,一般只是单向通道,只能在父子进程间使用,即使是流管道、命名管道等也不能同时支持双向传输和不相关进程之间的通信。因此nginx不考虑这两种进程间的通信方式。
linux进程间双工通信的实现
Linux平台上使用socketpair ()函数创建用于进程间双向通信的socket,该函数的原型为:intsocketpair(int d,int type,int protocol,in tsv[2] ) ;
使用该函数时,需要包含头文件sys/types.h,这里定义了一些用到的宏常量。该函数的4个参数的含义分别是:
d,socket的域,一般设置为AF_UNIX。
type,socket的类型,可以选择的有SOCK_STREAM和SOCK_DGRAM,前者提供面向连接的可靠传输,后者提供面向无连接的传输,用于进程间通信选择前者。
protocol,使用的协议,用于进程间通信时,赋值为0。
sv[2] ,指向存储文件描述符的指针,也就是创建好的两个socket的文件描述符指针。
使用该函数创建好的一对套接字是一对未命名的相互连接的UNIX族套接字。在实际的使用中,完全可以把这一对socket当作普通的文件描述符进行读写操作。该函数在Nginx服务器初始化过程中ngx_spawn_process()函数中被调用:
if(socketpair(AF_UNIX,SOCK_STREAM,0,ngx_processes[s] .channel)==-1)
{
ngx_log_error(NGX_LOG_ALERT,cycle->log,ngx errno,"socketpair()failed while spawning\"s\"", name) ;
return NGX INVALID_PID;
}
这一对套接字被称为channel,分别是channel[0] 和channel[1] ,一般channel[0] 用于向其他进程发送消息, channel[1] 用于监听其他进程发送来的消息事件。
在上边的源码中,socketpair() 函数的最后一个参数为ngx_processes[s] .channel,这里的ngx_processes是一个ngx_process_t结构体。
通过这对套接字发送消息和接收消息的方法和网络socket的方式是相同的, 都使用read()和write()函数,这里就不再赘述.
美编:刘咏江
责任编辑:瞿忠伟
轮值主编:王鹏
副总编:孙砚铭
总编:王珂
风信相随
铛铛相伴
长按扫码关注