如何将Linux包含flock的程序移植到Solaris

如何将包含flock的程序移植到Solaris

作者: Badcoffee
Email: blog.oliver@gmail.com
Blog: http://blog.csdn.net/yayong
20055

一个朋友的Linux源程序中包含如下调用:

flock(fd, LOCK_UN)

Linux上用gcc编译没有问题。但在Solaris上编译时,出错:error: `LOCK_EX' undeclared (first use in this function)
显然,这是因为没有include正确的头文件,导致无法找到LOCK_EX宏的定义所致。

但是,朋友查了solarisman,确信已经正确的include了头文件,下面是solaris man手册的说明:朋友已经grep/usr/include/sys/file.h确实没有发现LOCK_EX宏的定义。难道真的是solaris的头文件出了问题?

flock(3UCB)可以看出,该调用是属于man手册的section 33UCB字类中,
让我们看看3UCB是干什么用的:问题得到解决,原来3UCB的函数是为兼容BSD函数而保留下来的,果然按照说明,在/usr/ucbinclude/sys/file.h中找到了这个宏。

通过这么一查,发现section 3里的子类真的很多,以后查man的时候一定要留心。

man flock

SunOS
/ BSD Compatibility Library Functions flock(3UCB)

NAME
flock 
-  apply or remove an advisory  lock  on an open file

SYNOPSIS
/ usr / ucb / cc[ flag ... ] file ...
#include sys
/ file.h

int  flock( fd, operation);
int  fd, operation;

 

下面是常用的文件锁函数说明:

flock(); 
lockf(); 
fcntl();

flock()是从BSD中衍生出来的,但目前在大多数UNIX系统上都能找到,在单个主机上flock()简单有效,但它不能在NFS上工作。

Perl中也有一个有点让人迷惑的 flock()函数,但却是在perl内部实现的。 fcntl()是唯一的符合POSIX标准的文件锁实现,所以也是唯一可移植的。它也同时是最强大的文件锁——也是最难用的。

在NFS文件系统上,fcntl()请求会被递交给叫rpc.lockd的守护进程,然后由它负责和主机端的lockd对话,和flock() 不同,fcntl()可以实现记录层上的封锁。 lockf()只是一个简化了的fcntl()文件锁接口。无论你使用哪一种文件锁,请一定记住在锁生效之前用sync来更新你所有的文件输入/输出。

lock (fd);
write_to(some_function_of(fd));
flush_output_to(fd); 
/*  在去锁之前一定要冲洗输出  */
unlock(fd);
do_something_else;  
/*  也许另外一个进程会更新它  */
lock (fd);
seek(fd, somewhere); 
/*  因为原来的文件指针已不安全  */
do_something_with(fd);
 ...

一些有用的fcntl()封锁方法(为了简洁略去错误处理):

#include 
#include 
read_lock(
int  fd)   /*  整个文件上的一个共享的文件锁  */
{
    fcntl(fd, F_SETLKW, file_lock(F_RDLCK, SEEK_SET));
}

write_lock(
int  fd)  /*  整个文件上的一个排外文件锁  */  
{
    fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));  
}

append_lock(
int  fd)  /*  一个封锁文件结尾的锁, 其他进程可以访问现有内容  */    
{
    fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_END));
}

前面所用的file_lock函数如下:

struct  flock *  file_lock( short  type,  short  whence)
{
    
static   struct  flock ret ;
    ret.l_type 
=  type ;
    ret.l_start 
=   0  ;
    ret.l_whence 
=  whence ;
    ret.l_len 
=   0  ;
    ret.l_pid 
=  getpid() ;
    
return   & ret ;
}

而且根据solaris flock(3UCB)的说明,该函数不是线程安全的,因此,强烈建议用fcntl来取代flock,毕竟它才是POSIX的标准。

另外,对于很多大容量邮件系统的应用,邮箱是通过NFS共享的,更不能用flock来做了。在Solaris上, 可以使用下面的代码来实现一个新的flock:

#ifndef LOCK_SH
#define    LOCK_SH   1    /* shared lock */
#define    LOCK_EX   2    /* exclusive lock */
#define    LOCK_NB   4    /* don't block when locking */
#define    LOCK_UN   8    /* unlock */
#endif
#ifdef POSIX
#include 
/*
 * This function emulates a subset of flock()
 
*/
int  emul_flock(fd, cmd)
    
int  fd, cmd;
{    
struct  flock f;
    memset(
& f,  0 sizeof  (f));
    
if  (cmd  &  LOCK_UN)
        f.l_type 
=  F_UNLCK;
    
if  (cmd  &  LOCK_SH)
        f.l_type 
=  F_RDLCK;
    
if  (cmd  &  LOCK_EX)
        f.l_type 
=  F_WRLCK;
    
return  fcntl(fd, (cmd  &  LOCK_NB)  ?  F_SETLK : F_SETLKW,  & f);
}
#define  flock(f,c)      emul_flock(f,c)
#endif

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值