精华区 [关闭][返回]

当前位置:网易精华区>>讨论区精华>>编程开发>>C/C++>>资料汇编----------藏经阁>>Unix编程FAQ>>Unix编程FAQ第二章2-7节

主题:Unix编程FAQ第二章2-7节
发信人: tengel()
整理人: kevintz(2000-08-24 01:59:34), 站内信件
2.2关闭时我如何通知连接的另一端?
如果你试图从管道,套接字,FIFO(命名管道)中读取数据.当写的一端连接关闭时,
你将得到一个文件结束指示(read函数返回0字节).如果试图写一个管道,套接字等
.当读的一端关闭时,SIGPIPE信号将被传递该进程,如果该进程不捕获他,则进程将
被杀掉(如果你忽略或者阻塞该信号),write调用将失败于EPIPE.
2.3读目录的最好的方法?
在以前有多种接口实现他,现在,在Posix.l中仅有总重要的一个被定义在<dirent
.h>中.
函数opendir打开指定的目录;readdir以标准格式从中读目录的条目;closedir关
闭他.同时也提供了rewinddir,telldir和seekdir,他们的功能也很明显.
如果你想扩展一个带有通配符的文件名,那么大多数系统都又一个glob()函数;也
可以使用fnmatch检验匹配通配符的文件名,或者ftw检查整个目录树.
2.4怎样检查其他人是否也打开了一个文件?
这是另一个"FUQ(Frequently Unanswered Questions)",因为,在通常情况下,你的
程序对是否有其他程序打开一个文件并不感兴趣.如果你需要处理文件的并发存取
,那么你需要考虑咨询锁.
这样,通常情况下,做到这一点是很困难的.使用像fuser和lsof这样的工具辗转的
通过核心数据结构检测到文件打开是一种不健壮的方式,因为你得到一个文件是否
打开的时候,可能该信息已经过时了.
2.5如何锁定一个文件?
有三个主要的文件锁机制可用.他们都是"adbisory"(咨询的)[*],也就是说他们依
赖于程序按顺序的协作运行.所以在一个应用里所有的程序使用相同的锁机制是至
关重要的,在你的程序需要和第三方软件共享文件时需要给予更大的关注.
[*]Well, actually some Unices permit mandatory locking via the sgid bi
t-RPFM for this hack.

一些应用使用像'FILENAME.lock'一样锁定文件.简单的测试是否存在像这样的文
件是不充分的,因为一个进程可能在拥有该文件时被杀掉.被UUCP使用的方法(大概
最著名的例子是使用锁定文件来控制访问MODEM,远程系统等)是存储PID在锁定文
件中,然后测试该pid是否在运行.即使这样也不能保证正确(因为PIDs被循环使用
);他不得不拥有一个支持监测来查看一个Lockfie是否过时,这意味着拥有锁的进
程必须有规律的更新文件.

锁定函数:


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

flock起源于BSD, 现在几乎所有的Unix系统都可用(并不是全部).他在单个主机上
是简单和有效的,但是不能在NFS上工作.他锁定整个文件.现在比较流行的Perl程
序设计语言在他需要的地方实现了他自己的flock(),传达了真正可移植的想法.

fcntl是一个仅仅为了适应POSIX的加锁机制,是一个真正可以的锁.他的功能也很
强大,但是很难使用.对于挂接的NFS(网络文件系统),fctnl请求被传递到守护进程
,守护进程与在Server主机上的锁定通信.与flock不同的是,他可以在纪录级别加
锁.

lockf仅仅是fcntl加锁的简单编程接口.

无论你使用哪种加锁机制,在锁有效时同步你的文件IO操作都是很重要的:

    lock(fd);
    write_to(some_function_of(fd));
    flush_output_to(fd); /* NEVER unlock while output may be buffered 
*/
    unlock(fd);
    do_something_else;   /* another process might update it */
    lock(fd);
    seek(fd, somewhere); /* because our old file pointer is not safe *
/
    do_something_with(fd);
    ...

一个没有什么用处的fcntl锁的示范(为了简单忽略了错误处理):
#include <fcntl.h>
#include <unistd.h>

read_lock(int fd)   /* a shared lock on an entire file */
{
    fcntl(fd, F_SETLKW, file_lock(F_RDLCK, SEEK_SET));
}

write_lock(int fd)  /* an exclusive lock on an entire file */
{
    fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_SET));
}

append_lock(int fd) /* a lock on the _end_ of a file -- other
                       processes may access existing records */

    fcntl(fd, F_SETLKW, file_lock(F_WRLCK, SEEK_END));
}
The function file_lock used by the above is 

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如何发现一个文件是否被其他进程所更新?
这也是一个接近FUQ的问题,因为问这个问题的人们经常期当文件和目录改变的系
统通知,这没有一个简单的方法来得到他.(IRIX提供一个非标准的工具来监测文件
的存取,但是我没有在其他地方听说也可用).

一般来说,最好的方法是使用fstat函数在你要监测的文件上.(提示:fstat的花费
是很低的,通常比stat要低得多).通过查看文件的mtime和ctime,你可以检测什么
时候他被修改,删除,连接,重命名.

2.7du是如何工作的?
du使用stat(更精确的使用lstat)简单的查看所有的目录结构的每个文件,计算每
个文件使用的块的数量.
如果你想知道他工作的细节,简单答案是看源代码.
BSD系统的源代码(FreeBSD,NETBSD,OpenBSD)在他们的网站上都有解包的源代码
,GNU版本的工具在很多镜像上都有,你下载下来后需要解包.

--
                                           _
   O           @___       G               : \  
  /|__       /|/         /\|\             :  \
 /|/_       / /\         \ X_             :   \
  /  |     __/  \          | \      0     :    \
 /    0        0|          /              :     \

※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 210.14.224.57]

[关闭][返回]