fcntl+pthread_rwlock制作的支持多进程多线程混合的互斥锁
由于某些平台phtread_rwlock_ 系列是不支持进程间共享的属性, 而fcntl() 的文件记录锁又不安全用作线程之间互斥,是所以在多进程和多线程混合混合的服务器模型中, 互斥锁一般只能用信号灯或信号量机制, 但这都只有一种状态而没有共享锁(读)和独占锁(写)的区分, 对于多读少写的情况不太舒服.下面贴的代码是的实测平台为: FreeBSD-6.2, (正是freebsd不支持pthread_rwlockattr_set_pshared(attr, PTHREAD_PROCESS_SHARED ..)
flock_*** 系列的说明, 它可以类似pthread_rwlock_t 那样的使用, 但因为某些平台不支持PTHREAD_PROCESS_SHARED 的属性, 所以才特意写了我这段代码通过fcntl 记录锁来协调.
1) 数据类型: flock_t
2) 函数接口: (对于int 型的函数成功统一返回1, 失败返回0)
int flock_init(flock_t *fl, const char *fpath);
// 初始化fl 指向的flock_t 数据结构, fpath 指定要锁定的文件路径, NULL 则由系统自动创建临时文件
int flock_set_thread_safe(fockt_t *fl);
// 将fl 设置为线程安全(内部初始化类型为pthread_rwlock_t 的fl->plock)
int flock_wrlock(flock_t *fl);
// 取独占锁, 一般用于写
int flock_rdlock(flock_t *fl);
// 取共享锁
int flock_unlock(flock_t *fl);
// 解锁
void flock_destroy(flock_t *fl);
// 释放切毁锁
3) 通用宏(参数均为要加锁或解锁的文件描述符, 这些宏不具备线程安全):
FLOCK_WR_NB(fd); // 对fd取独占锁(无阻塞,成功返回1,失败返回0)
FLOCK_RD_NB(fd); // 对fd取共享锁(无阻塞,成功返回1,失败返回0)
FLOCK_WR(fd); // 对fd取独占锁(若已被占则自动阻塞等待)
FLOCK_RD(fd); // 对fd取共享锁(若已被独占则自动等待)
FLOCK_UN(fd); // 对fd释放锁
1. 代码之flock.h
#ifndef __FTPHP_FLOCK_20090530_H__
#define __FTPHP_FLOCK_20090530_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <fcntl.h>
#include <sys/types.h>
#include <pthread.h>
typedef struct {
int fd;
int flag;
pthread_rwlock_t plock;
} flock_t;
int flock_init(flock_t *fl, const char *fpath); // 1->ok, 0->failed
int flock_set_thread_safe(flock_t *fl); // set to thread safe, 1->ok, 0->failed
int flock_wrlock(flock_t *fl); // 1->ok, 0->failed
int flock_rdlock(flock_t *fl); // 1->ok, 0->failed
int flock_unlock(flock_t *fl);
void flock_destroy(flock_t *fl); // destroy flock
// error: 0, succ: 1
int flock_exec(int fd, int type, off_t offset, int whence, off_t len, int nonblock);
#define FLOCK_WR_NB(fd) flock_exec(fd, F_WRLCK, 0, SEEK_SET, 0, 1)
#define FLOCK_RD_NB(fd) flock_exec(fd, F_RDLCK, 0, SEEK_SET, 0, 1)
#define FLOCK_WR(fd) flock_exec(fd, F_WRLCK, 0, SEEK_SET, 0, 0)
#define FLOCK_RD(fd) flock_exec(fd, F_RDLCK, 0, SEEK_SET, 0, 0)
#define FLOCK_UN(fd) flock_exec(fd, F_UNLCK, 0, SEEK_SET, 0, 0)
#ifdef __cplusplus
}
#endif
#endif
2. 代码之flock.c
/**
flock
$Id: $
*/
#include "flock.h"
#include <errno.h>
#include <stdarg.h>
#include <unistd.h>
// error: 0, succ: 1
int flock_exec(int fd, int type, off_t offset, int whence, off_t len, int nonblock)
{
int rc;
struct flock fl;
if (fd < 0) return 0;
fl.l_type = type;
fl.l_start = offset;
fl.l_whence = whence;
fl.l_len = len;
fl.l_pid = 0;
do {
rc = fcntl(fd, nonblock ? F_SETLK : F_SETLKW, &fl);
} while (rc < 0 && errno == EINTR);
return (rc == 0);
}
// init (fpath = NULL, auto assigment)
int flock_init(flock_t *fl, const char *fpath)
{
// initilized?
if (fl->flag & 0x01)
flock_destroy(fl);
if (fpath == NULL)
{
char mypath[] = "/tmp/flk.XXXXXX";
fl->fd = mkstemp(mypath);
if (fl->fd >= 0)
unlink(mypath);
}
else
{
fl->fd = open(fpath, O_CREAT | O_RDWR, 0600);
}
fl->flag = 0x01;
return (fl->fd >= 0);
}
// thread safe
int flock_set_thread_safe(flock_t *fl)
{
if (pthread_rwlock_init(&fl->plock, NULL) == 0)
{
fl->flag |= 0x02;
return 1;
}
return 0;
}
// wrlock
int flock_wrlock(flock_t *fl)
{
if (!(fl->flag & 0x02) || pthread_rwlock_wrlock(&fl->plock) == 0)
return FLOCK_WR(fl->fd);
return 0;
}
// rdlock
int flock_rdlock(flock_t *fl)
{
if (!(fl->flag & 0x02) || pthread_rwlock_rdlock(&fl->plock) == 0)
return FLOCK_RD(fl->fd);
return 0;
}
// unlock
int flock_unlock(flock_t *fl)
{
if (FLOCK_UN(fl->fd) && (!(fl->flag & 0x02) || pthread_rwlock_unlock(&fl->plock) == 0))
return 1;
return 0;
}
// free flock only(not unlink the fl->fpath)
void flock_destroy(flock_t *fl)
{
if (fl->flag & 0x02)
pthread_rwlock_destroy(&fl->plock);
&nbs
补充:综合编程 , 其他综合 ,