咨询一个C语言的问题,关于linux删除文件的

我记得APUE上好像说过,文件被进程打开的情况下,它不会被立即删除,一直要到进程关闭这个文件后才会真正地被删除吧. 但是下面这段C代码的表现好像不太对啊

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#define CHECK(i) check(__LINE__,i)

void check(int iLine,int iRet)
{
  if(iRet == -1)
    {
      printf("[line:%d]%d:%s\n",iLine,iRet,strerror(errno));
    }
}

int main()
{
  const char* tmpfile = "test.part";
  const char* file = "test.full";
  int fd = open(tmpfile,O_TRUNC|O_CREAT|O_WRONLY,S_IRWXU);
  CHECK(fd);
  sleep(10);                    // 这个时候确认test.part是存在的.
  CHECK(unlink(tmpfile));
  CHECK(write(fd,"HELLO",5));
  fflush(stdout);
  CHECK(link(tmpfile,file));
  sleep(10);                    // 这个时候test.part就不见了,但是这个时候test.part还出于被打开的状态呀,为什么会这样?
  close(fd);
  return 0;
}

前面创建文件,删除文件,写入内容都没问题,后面的link操作会失败,提示"没有这个文件存在",然后我ls了一下,果然就不见了.

文件系统ext4

unlink(tmpfile) 把文件删掉了啊

APUE上说,文件被进程打开的情况下,它不会被立即删除,一直要到进程关闭这个文件后才会真正地被删除吧.

但是我在sleep的那个时间点上,一直都没有关闭这个文件. 所以这个时候文件应该存在才对,一直到程序退出后才会真正被删除.

我只能告诉你,眼见不一定为实! 虽然你看不见文件了,但是这个相关资源并没有被释放, 还且你还可以通过/proc/pid/fd访问这个文件。

按照我的理解,如果文件在被打开的情况下删除了,已经打开这个文件的process会继续拥有这个文件句柄的使用权,但是文件系统里标记为删除了。

我也知道资源并没有释放,因为后面的write操作是成功的.

我觉得你的理解应该是正确的.

unlink后就无法再通过文件名来访问该文件了,所以link函数会失败,但是文件内容还没有被删除,还能通过fd访问

用linkat来代替link应该就可以了,我试试看

文件实际上是由inode和文件本身数据data block组成,我们在目录下看到的只是到实际文件节点的一个link,调用 unlink实际上是将目录中指向实际文件的link删掉,当link为0,操作系统才会真正删除文件。 回到问题本身:

  1. open打开并创建这个文件,没问题,该进程获得fd这个文件描述符,属于进程资源。

  2. 等待10s后,unlink此文件,这里只是标记该文件要被删除,这时候,这个目录里的目录项肯定是被删除了,所以你ls是看不到了,但是并不代表文件不在了,

  3. 你fflush仍然可以把内容刷进文件内,但是你link的第一个tmpfile参数这时候是一条无效路径,这一步link会失败。

  4. 你close掉fd,退出进程,这时候进程释放fd,如果这时候文件实际link数为0,真的会被删除。

当然,你ls才调用unlink后就已经看不到目录下的这个文件了。。

1 个赞

解释好清楚,谢谢