c-fopen for write从不返回null



我正在尝试构建一些简单的东西来测试文件锁定。我试着打开两个文件进行写入,两个调用都完成了。打开文件后,上面写着:"你好,世界"。

#include <stdio.h>
int main() {
  File *fp1 = fopen("./test.txt", "w");
  fwrite("hello", 1, 5, fp1);
  File *fp2;
  if (fp2 = fopen("./test.txt", "w")) {
    fwrite("      world", 1, 11, fp2);
  }
}

从fopen的手册页中,我的印象是,如果一个文件是打开写的,第二个调用将返回null。我发现了一个类似的情况:使用fopen打开一个C中具有相同标志的文件;根据Adhip Gupta的回答,我试图检查<=0也不起作用。

我也试着使用fcntl.h中的open((。当我期望第二次调用为-1时,打印了两个文件描述符。

#include <stdio.h>
#include <fcntl.h>
int main() {
  int id1 = open("./text.txt", O_WRONLY);
  int id2 = open("./text.txt", O_WRONLY);
  printf("%d %dn", id1, id2);
}

为什么会出现这种情况?在进行测试时,我没有关闭文件流/描述符;这可能是原因吗?

这是因为当您使用"w"作为fopen的打开模式时,它会破坏文件的当前内容,并从一个新文件开始。因此,当你第二次调用fopen时,它会成功,因为它不在乎文件是否存在,也不在乎文件中是否有任何内容。如果路径正确,并且你有打开文件进行写入的正确权限,那么fopen调用就会成功。

如果你只想打开一个只用于写入的文件,而如果它已经存在则失败,你必须首先自己检查文件是否存在。

多次打开同一个文件是完全有效的。您提到了手册页和fcntl.h,所以我认为您正在开发一些unix变体。当应用程序打开文件进行写入时,Unix不会自动锁定文件。如果程序A和程序B打开同一个文件,它们的修改将相互覆盖;例如,当他们向文件的不同部分进行写入时,这很有用。在您的代码中,程序A和程序B是相同的过程。

打开同一个文件两次并不是特例。每次调用open都会给您一个文件描述符,每个文件描述符都有自己的位置。对fopen的每次调用都会为您提供一个文件描述符和一个stdio写入缓冲区。在第一个示例中,向每个文件写入一小段数据,fwrite调用将数据存储在内存中的写缓冲区中;直到调用CCD_ 9,数据才实际写入文件。您没有显式调用fflush(),也没有在后台调用fflush(或实现相同效果(的fclose()。当程序退出时,fclose()被隐式调用,但不能保证文件的关闭顺序,因此有两种可能性,您可以看到第二种:

  • fp1首先闭合,使得"hello"被写入位置0。然后fp2闭合,使得" world"被写入位置0。这将覆盖通过fp1写入的5个字节
  • fp2首先闭合,使得" world"被写入位置0。然后fp2闭合,使得"hello"被写入位置0。这将覆盖通过fp1写入的前5个字节,留下"hello world"

大多数unix系统只通过lockffcntl等函数提供协作锁。如果两个程序都在同一文件上调用lockf(fd, F_LOCK, size)(不一定通过同一文件描述符(,那么执行此操作的第二个程序将阻塞,直到第一个程序释放其锁定。任何程序仍然可以通过调用write来修改文件。一些unix变体(例如,Linux确实提供了强制锁,无论程序是否知道锁,这些锁都会影响程序。

最新更新