|
沙发

楼主 |
发表于 2009-7-30 18:49:59
|
只看该作者
再看 unlink
unlink() 一个文件有时会造成一种假象,文件好像明明已经被删除了,但从实际的运作工程中,文件似乎却又是存在的。利用这种 “假象”,可以做创建一些临时用的文件,这些文件在程序结束,或者等待关闭文件描述符时,才会真正的删除。这样的例子见:http://www.groad.net/bbs/read.php?tid=980
在 上面链接的实例中,创建了特定于客户端的 FIFO 文件,为了在程序结束时这些 FIFO 也会随之删除,而在程序未结束时仍然可以使用这些文件,其中使用了 unlink() 函数达到此目的。之前,这个问题也困扰了我一会,当时的思考方向是,为什么文件都被删除了,但进程间还能通讯?难道只是两个进程间只要互相知道了各自已打开中间文件的文件描述符后,即使是这个中间文件被删除了还能利用得到的文件描述符进行通讯?后来,才知道这种想法是错误的,实质原因正是因为用了 unlink() 的缘故。
下面有两个测试代码,一个负责读一个文件,一个负责写一个文件,还有一个中间文件 test.txt ,里面随便填写些什么内容或者为空。这两个程序当时是为了做实验,需要 GDB 进行单步调试观察,而不能全速运行查看结果。
测试代码-1-read_test.c :
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main (void)
{
char buf [128];
int fd;
int sndfd;
int n;
if ((fd = open ("test.txt", O_RDONLY)) == -1) {
perror("open");
exit(1);
}
buf [0] = (char)fd;
mkfifo ("send_fifo", 0777);
sndfd = open ("send_fifo", O_WRONLY);
write (sndfd, buf, 1);
unlink ("test.txt");
n = read (fd, buf, 128);
buf [n] = '\\0';
printf ("%s\\n", buf);
close (fd);
unlink ("send_fifo");
return (0);
} 测试代码-2-write_test.c:
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
int main (void)
{
int fd;
char buf [10];
char buffer [128] = "hello world";
int revfd;
if ((fd = open ("test.txt", O_WRONLY)) == -1) {
perror("write");
exit(1);
}
revfd = open ("send_fifo", O_RDONLY);
read (revfd, buf, 1); /*得到客户机对test.txt的文件描述符*/
write ((int)buf[0], buffer, 128);
close (fd);
return 0;
} 生成程序后,分别用 GDB 进行单步调试。当然这两个程序的目的是为了测试,证明之前 “文件已经删除,但利用业已打开的文件描述符也能进行进程间的通讯” 的错误想法!
在 read_test.exe 程序中,建立了一个 FIFO ,把打开 test.txt 后得到的文件描述符发送给 write_test.exe 。write_test.exe 接收到后,再返回到 read_test.exe 中,单步跟下,调用 unlink() 删除 test.txt 文件。这里注意,在步过unlink() 这个函数后,在另外一个终端窗口里用 ls 命令查看 test.txt 是否存在,可以看到命令的结果是找不到有此文件,但实际上这个文件本身并没有真正的删除,只是它的名字已经从目录条目表中被隔去,而 ls 命令查看文件就列出目录条目表中的条目信息( 目录下的文件名字 )。
最后,用 wite_test.exe 写一个 hello world ,然后用 read_test.exe 接收,一开始造成的疑惑出现了---"命名用 ls 命令查看不到文件所在,而这个 hello world 却仍然被 read_test.exe 接收到了!“实际情况是,read_test.exe 用 read() 读取到的内容仍然是来自 test.txt 。test.txt 真正被删除是两个程序都结束的时候! |
|