免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1854 | 回复: 0
打印 上一主题 下一主题

如何将Linux包含flock的程序移植到Solaris [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-05-11 17:01 |只看该作者 |倒序浏览
如何将Linux包含flock的程序移植到Solaris
作者: BadcoffeeEmail: blog.oliver@gmail.comBlog:
[color="#000080"]http://blog.csdn.net/yayong
2005年5月一个朋友的Linux源程序中包含如下调用:
flock(fd, LOCK_UN)
在Linux上用gcc编译没有问题。但在Solaris上编译时,出错:error: `LOCK_EX' undeclared (first use in this function)
显然,这是因为没有include正确的头文件,导致无法找到LOCK_EX宏的定义所致。
但是,朋友查了solaris的man,确信已经正确的include了头文件,下面是solaris 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;
朋友已经grep了/usr/include/sys/file.h确实没有发现LOCK_EX宏的定义
难道真的是solaris的头文件出了问题?
从flock(3UCB)可以看出,该调用是属于man手册的section 3的3UCB字类中,
让我们看看3UCB是干什么用的:
man -s 3 intro
.......
(3UCB)
           These functions constitute  the  Source  Compatibility
           (with  BSD  functions) library. It is implemented as a
           shared object, libucb.so,  but  is  not  automatically
           linked  by  the C compilation system. Specify -lucb on
           the cc command line to link with this  library,  which
           is  located in the /usr/ucb subdirectory.  Headers for
           this library are located within  /usr/ucbinclude.  See
           libucb(3LIBUCB).
......
问题得到解决,原来3UCB的函数是为兼容BSD函数而保留下来的,
果然按照说明,在/usr/ucbinclude/sys/file.h中找到了这个宏。
通过这么一查,发现section 3里的子类真的很多,以后查man的时候一定要留心。
下面是常用的文件锁函数说明:
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


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/768/showart_25402.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP