Chinaunix

标题: 写操作前,文件被删除会产生什么后果? [打印本页]

作者: dexo    时间: 2007-09-07 14:14
标题: 写操作前,文件被删除会产生什么后果?
删除文件后,写操作仍然能成功,
1。write/fprintf把buffer写到缓冲区,不知道底层的文件系统,可是fflush/fsync怎么也能成功,fsync是等待缓冲区写到磁盘才返回,那么那些东西写到哪里去了?

2。写文件前怎么检测文件已经被删除?
用access/stat检查?有效率高一点的办法吗?
作者: Jiangge    时间: 2007-09-07 14:31
原帖由 dexo 于 2007-9-7 14:14 发表
删除文件后,写操作仍然能成功,
1。write/fprintf把buffer写到缓冲区,不知道底层的文件系统,可是fflush/fsync怎么也能成功,fsync是等待缓冲区写到磁盘才返回,那么那些东西写到哪里去了?

2。写文件前怎 ...

你已经打开文件了,只有等你关闭文件了,文件才会真正被删除,所以你写时,这个文件是存在的

man 3 remove for details
作者: 塑料袋    时间: 2007-09-07 15:34
没什么后果。只要current -> files_struct->file -> dentry -> inode 这条连接存在,文件就一定可以读写。

我想你说的是sys_unlink。sys_unlink会根据dentry -> count 是否为0来决定如何处理。

count == 0,dentry没有进程引用dentry,则可以将dentry变negative,既取消dentry与inode的连接

count > 0,有进程正在引用dentry,则不能改变dentry是positive还是nagetive,只能将dentry从hash中删除,使其对其他所有进程不可见。但是对于已经引用了dentry的进程而言,他们可以通过current -> files_struct->fd [ x ]-> f_dentry来找到这个dentry,进而读写inode。



access/stat是什么?
作者: MingLin1231    时间: 2007-09-07 16:45
3楼朋友的分析很到位
作者: dexo    时间: 2007-09-07 16:47
不好意思,没说清楚,
如下代码:
int fd = creat("t.txt",O_CREAT|O_WRONLY|O_TRUNC);
  char buf[20];
  for (int i=0; i<50; ++i)
    {
      snprintf(buf,20,"%d\n",i);
    write(fd,buf,strlen(buf))
    fsync(fd)
      sleep(1);
    }

循环过程中把t.txt删除掉(在命令行rm -rf t.txt),write、fsync调用都会返回0。
那write写的buf写到哪里去了?

我希望t.txt文件被删除后,重新创建文件,不至于把删除后写的东西都丢失。
怎么检测t.txt是否被删除了呢?

int access ( PathName, Mode)
int stat ( Path, Buffer)
write前调用access or stat检查文件是否存在,这个是不是效率低了点啊?
作者: dexo    时间: 2007-09-07 16:55
标题: 回复 #3 塑料袋 的帖子
其他进程(rm -rf)删除t.txt,write函数还是把内容写到t.txt文件去了?这是这个文件不是有效的,除了他本身外,谁都读不到了?????

但是我希望如果这个文件“不是有效的”后,重新创建,不能把之后write写的东西丢失。

[ 本帖最后由 dexo 于 2007-9-7 16:58 编辑 ]
作者: 塑料袋    时间: 2007-09-07 17:44
原帖由 dexo 于 2007-9-7 16:55 发表
其他进程(rm -rf)删除t.txt,write函数还是把内容写到t.txt文件去了?这是这个文件不是有效的,除了他本身外,谁都读不到了?????

但是我希望如果这个文件“不是有效的”后,重新创建,不能把之后wri ...



1)是这样的

2)想重新创建的话,可以用sys_fcntl,租借锁锁上这个文件,这样在删除前,会给你个信号。
作者: 思一克    时间: 2007-09-07 20:21
这是一个非常好的功能。

如果你用文件不是为了将内容永久保留在磁盘,而是为了通过文件传递数据,那么creat(open)后就立即unlink. 打开的文件fd则继续用来做你想要做的事情read, write。文件关闭后,磁盘上则不留痕迹。
作者: dexo    时间: 2007-09-07 21:05
原帖由 塑料袋 于 2007-9-7 17:44 发表



1)是这样的

2)想重新创建的话,可以用sys_fcntl,租借锁锁上这个文件,这样在删除前,会给你个信号。


sys_fcntl是什么?
google不到
作者: 塑料袋    时间: 2007-09-07 21:10
是个系统调用

加强制锁,租借锁.............
还有一个inode -> i_notify链也是由这个系统调用来设置,notify的作用也是在删除,连接,,重命名文件等操作时,给你个信号,同样能知道文件是否已被删除.

不过闹不清这个系统调用对应哪个库函数
作者: dexo    时间: 2007-09-09 17:38
inode -> i_notify 这个是文件系统内部的东西吧,没有对应的系统接口。
作者: dexo    时间: 2007-09-09 17:46
apue中:强制性锁机制对unlink函数没有影响。
作者: 塑料袋    时间: 2007-09-09 19:05
可以使用notify,最后会给你个信号.  

用sys_fcntl来设置notify.应该每个系统调用都有与其对应的C库函数
作者: dexo    时间: 2007-09-09 20:46
原帖由 塑料袋 于 2007-9-9 19:05 发表
可以使用notify,最后会给你个信号.  

用sys_fcntl来设置notify.应该每个系统调用都有与其对应的C库函数


man sys_fcntl
No manual entry for sys_fcntl
sys_fcntl在哪个头文件?
google到在 sys/syscall.h
打开这个文件没有?



感谢大家帮助。
并特别感谢塑料袋。
作者: 塑料袋    时间: 2007-09-09 22:16
sys_fcntl不属于哪个头文件,而是一个系统调用

google了个例子.

#include <fcntl.h>
#include <signal.h>
#include <stdio.h>
#include <unistd.h>


int main(int argc, char **argv){
    struct sigaction action;
    int fd;
    ..............................................

    /**************************************/
    fcntl(fd, F_NOTIFY, DN_MODIFY | DN_CREATE | DN_MULTISHOT);   /* 你想删除时收到通知的话,第三个参数为DN_DELETE | DN_MULTISHOT*/

   /****************************************/
    while(1){
        pause();
        printf("got event on fd=%d\n", event_fd);
    }
}
作者: dexo    时间: 2007-09-10 10:24
原帖由 塑料袋 于 2007-9-9 22:16 发表
sys_fcntl不属于哪个头文件,而是一个系统调用

google了个例子.

#include
#include
#include
#include


int main(int argc, char **argv){
    struct sigaction action;
    int fd;
    . ...


多谢!
这个完全能达到我的目的。

但是F_NOTIFY只有linux支持,

开始我忘记说运行环境了,是AIX,
(最好能)在solaris、linux上也能跑。(这点,各位别奇怪,领导的要求啊)
作者: dexo    时间: 2007-09-10 10:29
用F_NOTIFY aix做关键字google到:

Well we can do directory change notification, we just potentially have to
scan the directory to do it without kernel support !
作者: zhangshebao    时间: 2007-09-17 06:48
原帖由 dexo 于 2007-9-7 16:47 发表
不好意思,没说清楚,
如下代码:
int fd = creat("t.txt",O_CREAT|O_WRONLY|O_TRUNC);
  char buf[20];
  for (int i=0; i


楼主每次写前打开(生成、添加)不就行了:
int fd = creat("t.txt",O_CREAT|O_WRONLY|O_TRUNC);
close(fd);
  char buf[20];
  for (int i=0; i<50; ++i)
    {
      snprintf(buf,20,"%d\n",i);
    fd = open("t.txt",O_CREAT|O_WRONLY|O_APPEND);
    write(fd,buf,strlen(buf));
//    fsync(fd);
    close(fd);
      sleep(1);
    }
作者: iceviewer    时间: 2007-09-17 10:07
如果每次写之前都打开一次,写完以后关闭一次,不知道会不会对效率产生较大影响。。。




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2