文章9:Nginx accept互斥锁
来源:互联网 发布:js 数字转换为汉字 编辑:程序博客网 时间:2024/06/05 04:30
欢迎转载,转载请注明出处http://blog.csdn.net/yankai0219/article/details/8453317
文章内容
0.序
文章内容
0.序
1.Nginx锁的核心数据结构
2.分析文件锁
0.序
强烈推荐的文章是nginx中锁的设计以及惊群的处理,本文只是对文章中的内容进行了部分总结和部分解释。
Nginx之所以要采用Accept互斥锁就是为了避免惊群现象。所谓惊群现象:指一个fd的事件被触发后,等候这个fd的所有线程/进程都被唤醒。虽然都被唤醒,但是只有一个会去响应。
Nginx使用的锁分为两种情况:1)一种是支持原子操作的情况,由NGX_HAVE_ATOMIC_OPS这个宏来进行控制的。2)一种是不支持原子操作的情况,使用文件锁来实现。
用户空间进程间锁的实现的原理很简单,就是弄出一个让所有进程共享的东西,比如mmap的内容或文件,然后通过这个东西来控制进程的互斥。
1.Nginx锁的核心数据结构
Nginx中锁的核心数据结构,也就是Nginx使用哪个变量来控制进程的行为。
- typedef struct {
- #if (NGX_HAVE_ATOMIC_OPS)
- ngx_atomic_t *lock; //原子操作
- #else
- ngx_fd_t fd; //fd表示进程间共享的文件句柄
- u_char *name; //name表示文件名
- #endif
- } ngx_shmtx_t;
2.分析文件锁
由于本人对原子操作不了解,因此只能分析一下文件锁。Nginx使用文件锁,实际上就是APUE 14.3 记录锁中内容。
上锁:ngx_trylock_accept_mutex----------------->ngx_shmtx_trylock--------------->ngx_trylock_fd
删除锁:ngx_shmtx_unlock------------------------->ngx_unlock_fdngx_int_t
ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
{
ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"accept mutex locked");
/*ngx_accept_mutex_held 获得锁的标志,如果本来已经获得锁,则直接返回OK*/
if (ngx_accept_mutex_held
&& ngx_accept_events == 0
&& !(ngx_event_flags & NGX_USE_RTSIG_EVENT))
{
return NGX_OK;
}
ngx_shmtx_unlock(&ngx_accept_mutex);
return NGX_ERROR;
}
ngx_accept_events = 0;
ngx_accept_mutex_held = 1;/*获得锁的标识*/
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"accept mutex lock failed: %ui", ngx_accept_mutex_held);
return NGX_ERROR;
}
ngx_accept_mutex_held = 0;
}
return NGX_OK;
}ngx_shmtx_trylock(ngx_shmtx_t *mtx){
ngx_err_t err;
err = ngx_trylock_fd(mtx->fd);
if (err == 0) {
return 1;
}
}ngx_err_t
ngx_trylock_fd(ngx_fd_t fd)
{
struct flock fl;
ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &fl) == -1) {
return ngx_errno;
}
return 0;
}
ngx_trylock_accept_mutex(ngx_cycle_t *cycle)
{
/*ngx_shmtx_trylock通过fcntl对ngx_accept_mutex中fd成员变量上锁,锁定整个文件*/
if (ngx_shmtx_trylock(&ngx_accept_mutex)) {/*锁定成功*/ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"accept mutex locked");
/*ngx_accept_mutex_held 获得锁的标志,如果本来已经获得锁,则直接返回OK*/
if (ngx_accept_mutex_held
&& ngx_accept_events == 0
&& !(ngx_event_flags & NGX_USE_RTSIG_EVENT))
{
return NGX_OK;
}
/*ngx_enable_accept_events将cycle->listening中的端口号都加到epoll事件中。把进程对应的监听socket 放入到epoll中进行监听,这样只有该进程能监听到accept操作。*/
if (ngx_enable_accept_events(cycle) == NGX_ERROR) {ngx_shmtx_unlock(&ngx_accept_mutex);
return NGX_ERROR;
}
ngx_accept_events = 0;
ngx_accept_mutex_held = 1;/*获得锁的标识*/
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"accept mutex lock failed: %ui", ngx_accept_mutex_held);
/*//如果我们前面已经获得了锁,然后这次获得锁失败,则说明当前的listen句柄已经被其他的进程锁监听,因此此时需要从epoll中移出调已经注册的listen句柄。这样就很好的控制了子进程的负载均衡 */
if (ngx_accept_mutex_held) { /*ngx_disable_accept_events将cycle->listening中的端口号从epoll事件中删除*/
if (ngx_disable_accept_events(cycle) == NGX_ERROR) {return NGX_ERROR;
}
ngx_accept_mutex_held = 0;
}
return NGX_OK;
}ngx_shmtx_trylock(ngx_shmtx_t *mtx){
ngx_err_t err;
err = ngx_trylock_fd(mtx->fd);
if (err == 0) {
return 1;
}
}ngx_err_t
ngx_trylock_fd(ngx_fd_t fd)
{
struct flock fl;
ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &fl) == -1) {
return ngx_errno;
}
return 0;
}
删除锁的操作
void
ngx_shmtx_unlock(ngx_shmtx_t *mtx)
{
ngx_err_t err;
err = ngx_unlock_fd(mtx->fd);
if (err == 0) {
return;
}
ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
}ngx_err_t
ngx_unlock_fd(ngx_fd_t fd)
{
struct flock fl;
ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &fl) == -1) {
return ngx_errno;
}
return 0;
}
ngx_shmtx_unlock(ngx_shmtx_t *mtx)
{
ngx_err_t err;
err = ngx_unlock_fd(mtx->fd);
if (err == 0) {
return;
}
ngx_log_abort(err, ngx_unlock_fd_n " %s failed", mtx->name);
}ngx_err_t
ngx_unlock_fd(ngx_fd_t fd)
{
struct flock fl;
ngx_memzero(&fl, sizeof(struct flock));
fl.l_type = F_UNLCK;
fl.l_whence = SEEK_SET;
if (fcntl(fd, F_SETLK, &fl) == -1) {
return ngx_errno;
}
return 0;
}
- 文章9:Nginx accept互斥锁
- 文章9:Nginx accept互斥锁
- nginx的accept互斥锁
- nginx accept 加锁
- nginx 处理accept
- nginx中accept处理
- nginx 处理accept
- Nginx Accept-Ranges
- Nginx文章
- Nginx 文章
- Nginx源代码分析之accept(十)
- Nginx源代码分析之accept(十六)
- accept()
- accept
- ACCEPT
- Accept
- accept
- Accept
- C风格字符串结束符用作逻辑判断
- 文章6:Nginx中的Epoll事件处理机制
- 文章8:Nginx中与Master-Worker进程通信有关的内容
- Cocos2D-X学习笔记(二)
- 堆内存和栈内存
- 文章9:Nginx accept互斥锁
- scws的学习笔记
- 文本链接与裸链对百度SEO的作用
- Discuz! NT 到 Discuz! X2.5 转换程序
- hdu 1251 字典树
- FindFirstFile Function
- Ubuntu 下 Android NDK 开发环境搭建
- MINA2.0用户手册中文版--第六章 MINA中的传输 第一节 基于APR的传输
- 李默芳