使用记录锁实现进程间锁
Posted in linux on 二月 12th, 2010 by kafka0102
在一篇比较lightty和nginx实现机制的文章中提到,nginx相比于lightty,在多work进程accept时做了加锁处理,对于linux2.4之前的版本,不加锁会出现“惊群现象”。之前也隐约记得,apache对多进程的accept也是做了加锁处理。对这方面不是很熟悉,所以就翻看nginx代码查找加锁的实现代码,最后确认是使用的文件记录锁(record lock),APUE上有详细说明,这里只简单的摘取说明。
加锁解锁的系统接口是:
fcntl(int fd, int cmd, struct flock *flockptr);
其中cmd 为F_GETLK、 F_SETLK(非阻塞加锁) 或 F_SETLKW(阻塞加锁), flockptr 指向 flock结构。flock结构如下:
struct flcok { short int l_type; /* 锁定的状态*/ short int l_whence;/*决定l_start位置*/ off_t l_start; /*锁定区域的开头位置*/ off_t l_len; /*锁定区域的大小*/ pid_t l_pid; /*锁定动作的进程*/ };
l_type 有三种状态:1)F_RDLCK 建立一个供读取用的锁定,2)F_WRLCK 建立一个供写入用的锁定,3)F_UNLCK 删除之前建立的锁定。
对于nginx accept加排他锁,需要设置l_whence=SEEK_SET、l_start=0、l_len=0。
加锁和解锁函数类似于:
int lock_file(int fd) { struct flock s_flock; s_flock.l_type = F_WRLCK; s_flock.l_whence = SEEK_SET; s_flock.l_start = 0; s_flock.l_len = 0; s_flock.l_pid = getpid(); return fcntl(fd, F_SETLKW, &s_flock); } int unlock_file(int fd) { return fcntl(fd, F_SETLKW, F_UNLCK); }
Nginx中accpet锁变量是ngx_accept_mutex,nginx会在主进程初始化event module时调用ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name)来初始化锁。该函数一个有意思的地方是,在open锁文件得到fd后,nginx又调用unlink删掉文件,实际上并不存在这样一个实体的锁文件,而后各work进程共用该fd来做加锁解锁操作。
=============================== 华丽的终止符 ================================
随机日志
Leave a Comment