使用记录锁实现进程间锁

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来做加锁解锁操作。


=============================== 华丽的终止符 ================================

本文作者:kafka0102,转载文章请注明来源,谢谢!!
本文链接:http://www.kafka0102.com/2010/02/50.html


  

随机日志


Leave a Comment