【问题标题】:Understanding functioning of read() and lseek() in C了解 C 中 read() 和 lseek() 的功能
【发布时间】:2017-08-28 10:24:09
【问题描述】:

当我们使用系统调用 open() 然后执行 I/O 操作(尤其是 read() 和 lseek())时,如果我们在程序仍在运行时更改文件,内核缓冲区是否会更新?如果没有,那么如何将实时更新文件强制同步到内核缓冲区。

这是一个例子:

    #include <stdio.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    int main()
    {
            int fd=0;
            char ch='\0';
            fd=open("test.dat",O_RDONLY);
            while(1)
            {
                    while(read(fd,&ch,1)!=0)
                    {
                            printf("%c",ch);
                    }
                    printf("\n");
                    lseek(fd,0,SEEK_SET);
                    sleep(5);
            }
            close(fd);
            return 0;
    }

现在,我在“test.dat”中有一些数据(比如:'3 3 34')。我打开了这个文件并阅读它以结束,然后再次寻找它开始。同时,在一些编辑器中,我打开了这个“test.dat”文件并更新了它的内容并保存了它们。由于 read() 和 lseek() 是系统调用,如果内核/操作系统缓冲区定期与硬盘中的文件同步,它们应对应于更新文件的更改。但事实并非如此。文件中的更改不会从 read() 中反映出来,而是继续打印初始内容。对于写作,如果有sync()、fsync()等解决方案。但是对于阅读,我们有一些这样的功能吗?

(注意:这个问题的一个简单的解决方案是 close() 和 open() 文件描述符,它完美地工作,但我想知道和理解一些不关闭文件描述符的替代方法)

【问题讨论】:

  • 您需要这两个应用程序才能在共享启用模式下打开文件。您可以在程序中执行此操作,请参阅open 的选项。您可能无法强制第 3 方应用更改其打开模式。
  • 小心,read 出错时返回 -1-1 != 0 所以如果出现错误,你的循环将变成无限循环。哦,你真的应该检查open 调用的结果。
  • 至于你的问题,有程序不断地从文件中读取。带有-f 选项的tail 就是这样一种程序。也许您可以查看该程序的源代码以了解它是如何工作的?
  • 您的编辑器可能正在将您的原始文件移动到备份中,并创建一个新文件(编辑所在的位置)。您可以使用 stat 命令轻松地再次检查,并查看在编辑文件后 inode 是否在您身上发生变化。如果您不想追求所有这些,只需使用 echo 命令附加到您的文件中,看看是否有效。

标签: c linux


【解决方案1】:

有些编辑者会复制他们编辑的文件,最后将其移动到原始文件名中(可能将原始文件重命名为其他名称),因此您正在阅读的文件实际上可能与编辑者编辑过的文件不同.这取决于您使用哪个编辑器来修改文件,并且是一项复杂的任务,因为您可以有多个指向文件的链接,因此预计此操作不是由编辑器完成的。确保您正在修改原始文件。有用的是拥有不同的内容文件并执行(而不是编辑文件)

$ your_program your_file.txt &
$ cat modified_version.txt > your_file.txt

看看会发生什么。

您尚未公开您用于编辑文件的编辑器。

【讨论】:

  • 感谢大家澄清这一点,当我的程序仍在执行时,我在从编辑器 (vim) 保存对文件的更改后执行了“ls -ilrta”。我看到了这个文件“.nfs000000*”(由编辑器创建的临时文件)。在执行程序之前,它的 inode 编号与文件匹配。编辑器保存的新文件被赋予了新的 inode 编号。
  • 这有点奇怪,就好像你有一个多链接文件一样,你丢失了其余的链接以支持旧文件,并打破了这个链接使用新文件的链接。我认为旧的vi 覆盖了文件以允许文件系统保留未触及的链接。
  • 如果我使用 echo 命令或其他 C 程序修改文件,而不是 vim 编辑器,则被修改文件的 inode 编号保持不变,因此正在运行的程序会检测到它
猜你喜欢
  • 1970-01-01
  • 2019-09-01
  • 2014-04-17
  • 2011-04-21
  • 2015-04-17
  • 2013-02-27
  • 2020-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多