文件锁方法 in LINUX

2.1.3 我是否可以同时使用SysV IPC和select()/poll()?
---------------------------------------------------
*不能。* (除非在AIX上,因为它用一个无比奇怪的方法来实现这种组合)

一般来说,同时使用select()或poll()和SysV 消息队列会带来许多麻烦。SysV
IPC的对象并不是用文件描述符来处理的,所以它们不能被传递给select()和
poll()。这里有几种解决方法,其粗暴程度各不相同:
   - 完全放弃使用SysV IPC。 :-)
   - 用fork(),然后让子进程来处理SysV IPC,然后用管道或套接口和父进程
     说话。父进程则使用select()。
   - 同上,但让子进程用select(),然后和父亲用消息队列交流。
   - 安排进程发送消息给你,在发送消息后再发送一个信号。*警告*:要做好
     这个并不简单,非常容易写出会丢失消息或引起死锁的程序。
……另外还有其他方法。

2.2 我如何才能知道和对方的连接被终止?
======================================
如果你在读取一个管道、套接口、FIFO等设备时,当写入端关闭连接时,你将会
得到一个文件结束符(EOF)(read()返回零字节读取)。如果你试图向一个管道或
套接口写入,当读取方关闭连接,你将得到一个SIGPIPE的信号,它会使进程终
止除非指定处理方法。(如果你选择屏蔽或忽略信号,write()会以EPIPE错误退
出。)

2.3 什么是读取目录的最好方法?
==============================
历史上曾有过许多不同的目录读取方法,但目前你应该使用POSIX.1标准的
<dirent.h>接口。

opendir()函数打开一个指定的目录;readdir()将目录以一种标准的格式读入;
closedir()关闭描述符。还有一些其他如rewinddir()、telldir()和seekdir()
等函数,相信不难理解。

如果你想用文件匹配符('*','?'),那么你可以使用大多数系统中都存在的glob()
函数,或者可以查看fnmatch()函数来得到匹配的文件名,或者用ftw()来遍历整
个目录树。

2.4 我如何才能知道一个文件被另外进程打开?
==========================================
这又是一个“经常不被回答的问题”,因为一般来说你的程序不会关心文件是否
正被别人打开。如果你需要处理文件的并发操作,那你应该使用咨询性文件锁。

一般来说要做到这点很难,像fuser或lsof这样可以告诉你文件使用情况的工具
通过解析内核数据来达到目的,但这种方法十分不健康!而且你不能从你的程序
中调用它们来获取信息,因为也许当它们执行完成之后,文件的使用状况在瞬间
又发生了变化,你无法保证这些信息的正确。

2.5 我如何锁住一个文件?
========================
有三种不同的文件锁,这三种都是“咨询性”的,也就是说它们依靠程序之间的
合作,所以一个项目中的所有程序封锁政策的一致是非常重要的,当你的程序需
要和第三方软件共享文件时应该格外地小心。

有些程序利用诸如 FIlENAME.lock 的文件锁文件,然后简单地测试此类文件是否
存在。这种方法显然不太好,因为当产生文件的进程被杀后,锁文件依然存在,
这样文件也许会被永久锁住。UUCP中把产生文件的进程号PID存入文件,但这样做
仍然不保险,因为PID的利用是回收型的。

这里是三个文件锁函数:
     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 <fcntl.h>
     #include <unistd.h>
    
     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 ;
     }

2.6 我如何能发现一个文件已由另外一个进程更新?
==============================================
这又几乎是一个经常不被回答的问题,因为问这个问题的人通常期待能有一个系
统级的告示来反映当前目录或文件被修改,但没有什么保证移植性的实现方法,
IRIX有一个非标准的功能用来监测文件操作,但从未听说在其他平台上也有相类
似的功能。

一般来说,你能尽的最大努力就是用fstat()函数,通过监视文件的mtime和ctime
你能得知文件什么时候被修改了,或者被删除/连接/改名了,听起来很复杂,所
以你应该反思一下为什么你要做这些。

2.7 请问du是怎样工作的?
========================
du只简单地用stat()(更准确地说是用lstat()函数)遍历目录结构中的每个文件
和目录,并将它们所占用的磁盘块加在一起。

如果你想知道其中细节,总是这么一句话:“读下源代码吧,老兄!”

BSD(FreeBSD、NetBSD和OpenBSD)的源代码在这些发行的FTP网站的源码目录里,
GNU版本的源码当然可以在任何一个GNU镜像站点中找到——前提是你自己懂得如
何解包。

2.8 我如何得到一个文件的长度?
==============================
用stat()或在文件打开后用fstat()。

这两个调用会将文件信息填入一个结构中, 其中你能找到诸如文件主人、属性、
大小、最后访问时间、最后修改时间等所有关于此文件的东西。

下面的程序大体示范如何用stat()得到文件大小。

     #include <stdlib.h>
     #include <stdio.h>
    
     #include <sys/types.h>
     #include <sys/stat.h>
    
     int get_file_size(char *path,off_t *size)
     {
       struct stat file_stats;
    
       if(stat(path,&file_stats))
         return -1;
    
       *size = file_stats.st_size;
       return 0;
     }

文章引用自:http://www.chinaaspx.com/article/unix.linux/58.htm

你可能感兴趣的:(FileLock,文件锁)