本章我们讲述一下nginx中进程之间互斥锁的实现。

1. ngx_shmtx_sh_t数据结构

#ifndef _NGX_SHMTX_H_INCLUDED_
#define _NGX_SHMTX_H_INCLUDED_


#include <ngx_config.h>
#include <ngx_core.h>


typedef struct {
    ngx_atomic_t   lock;
#if (NGX_HAVE_POSIX_SEM)
    ngx_atomic_t   wait;
#endif
} ngx_shmtx_sh_t;

本结构作为实现nginx进程间互斥锁的辅助存在,要求必须存放与共享内存中。

  • lock: 作为原子变量,用于实现互斥

  • wait: 采用POSIX信号量实现信号通知机制。这里要与ngx_shmtx_wakeup联系起来,用于强制解锁。

2. ngx_shmtx_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;
    sem_t          sem;
#endif
#else
    ngx_fd_t       fd;
    u_char        *name;
#endif
    ngx_uint_t     spin;
} ngx_shmtx_t;

本数据结构用于实现进程间的互斥锁。当支持NGX_HAVE_ATOMIC_OPS宏定义时采用原子锁来实现,否则采用文件锁来实现。当前我们支持GCC的NGX_HAVE_ATOMIC_OPS原子操作。

下面我们简要介绍一下各字段的含义:

  • lock: 用于实现原子锁

  • wait: 可以用于记录当前正在sem_wait()信号量的请求者数量。当前我们支持NGX_HAVE_POSIX_SEM宏定义

  • semaphore: 用于记录信号量是否创建成功

  • sem: linux信号量。用于辅助实现NGINX互斥锁,可以获得较高的性能

  • fd: 用于实现文件锁的句柄

  • name: 文件的名称

  • spin: 当不能马上获取到锁时,会采用自旋的方式pause CPU,这里用于控制每一次主动让出CPU之前(通过调用ngx_sched_yield()),进行自旋的次数。

3. 相关函数声明

// 创建一把'nginx进程间互斥锁'
ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr,
    u_char *name);

// 销毁互斥锁
void ngx_shmtx_destroy(ngx_shmtx_t *mtx);

// 尝试获取互斥锁
ngx_uint_t ngx_shmtx_trylock(ngx_shmtx_t *mtx);

//获取互斥锁
void ngx_shmtx_lock(ngx_shmtx_t *mtx);

//解锁
void ngx_shmtx_unlock(ngx_shmtx_t *mtx);

//强制解锁
ngx_uint_t ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid);


#endif /* _NGX_SHMTX_H_INCLUDED_ */



[参看]

  1. nginx源码分析1———进程间的通信机制一(信号量)

  2. Nginx的锁的实现以及惊群的避免

  3. Nginx源代码分析之锁的实现(十八)

  4. Nginx—进程锁的实现

  5. linux进程锁

  6. 进程间同步(进程间互斥锁、文件锁)

  7. nginx之共享内存