当前位置:编程学习 > 网站相关 >>

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
补充:综合编程 , 其他综合 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,