Nginx进程之间的通信机制介绍
进程之间的通信方式如共享内存,套接字、管道、消息队列、信号等。Nginx框架选择了三种方式:共享内存、套接字、信号来访问共享资源。同时Nginx使用了原子操作、信号量、文件锁来实现各个进程直降安全有序的访问资源。
1.共享内存
共享内存是Linux下提供的最基本的进程间的通信方式,他通过mmap或者shmget系统调用内存中创建了一块连续的线性地址空间,通过munmap或者shmdt系统释放内存。Nginx系统封装了ngx_shmtx_t结构体, 用于描述一块共享内存。
1.1数据结构
typedef struct {
ngx_atomic_t lock;
#if (NGX_HAVE_POSIX_SEM)
ngx_atomic_t wait;
#endif
} ngx_shmtx_sh_t;
typedef struct {
#if (NGX_HAVE_ATOMIC_OPS)/*宏定义采用原子锁控制共享内存*/
ngx_atomic_t *lock;
#if (NGX_HAVE_POSIX_SEM)/*宏定义采用信号量控制内存共享*/
ngx_atomic_t *wait;
ngx_uint_t semaphore;/*等于1,表示成功初始化信号量了*/
sem_t sem;/*信号量,决定内存是否在进程间共享*/
#endif
#else
ngx_fd_t fd;/*文件锁控制共享内存*/
u_char *name;
#endif
ngx_uint_t spin;
} ngx_shmtx_t;
1.2.创建共享内存
ngx_int_t
ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name)
{
mtx->lock = &addr->lock;
if (mtx->spin == (ngx_uint_t) -1) {
return NGX_OK;
}
mtx->spin = 2048;
#if (NGX_HAVE_POSIX_SEM)
mtx->wait = &addr->wait;
if (sem_init(&mtx->sem, 1, 0) == -1) {
ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,
"sem_init() failed");
} else {
mtx->semaphore = 1;
}
#endif
return NGX_OK;
}
2.Nginx频道
ngx_channel_t频道使用套接字实现(socketpair 方法),它用于创建父子进程间使用的套接字,是Nginx master进程和worker进程之间通信的工具。
2.1 chanel结构体
typedef struct {
ngx_uint_t command;/*TCP 消息中的命令*/
ngx_pid_t pid;/*进程ID,一般是发送命令方的进程*/
ngx_int_t slot;/*在ngx_process进程间的序号*/
ngx_fd_t fd;/*通信套接字的句柄*/
} ngx_channel_t;
2.socketpair方法介绍
Nginx工作时master进程会fork出n个worker进程(具有相同的工作逻辑和功能)。父进程复杂监听信号,通过 socket pair把信号传递给子进程(子进程之间一般不通信)。
3.信号
信号是一种非常短的消息,用于进程之间传递消息。Nginx通过定义ngx_signal_t结构体用于描述接收到信号时的行为。
typedef struct {
int signo;/*需要处理的信号*/
char *signame;/*信号对应的字符串名称*/
char *name;/*这个信号对应着的 Nginx 命令*/
void (*handler)(int signo, siginfo_t *siginfo, void *ucontext);/*收到 signo 信号后就会回调 handler 方法*/
}ngx_signal_t;