【问题标题】:Truncate file affect the read process截断文件影响读取过程
【发布时间】:2017-11-26 10:14:10
【问题描述】:

最近,我正在阅读 UNIX 系统编程,并进行了一些测试。 我很困惑为什么我在终端中使用 truncate 命令截断文件,然后读取过程读取相同的位置返回 0,它之前返回字符串“a”。进程打开文件,它会缓存文件,因为我改变了文件内容,然后读取,结果还是一样没有改变,那么为什么truncate file会立即影响进程呢?在UNIX系统编程中,它说v节点包括当前文件大小?所以不是每次都从磁盘读取大小,而是缓存在内存中。

读取过程代码源。

#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>

int main(int argc, char *argv[])
{
    int fd = open("a.txt", O_RDONLY);
    char buf[1024];
    int n;
    for(int i = 0;i < 10; i++){
        if (lseek(fd, 0, 0) == -1){
            return 1;
        }
        n = read(fd, buf, 1);
        if (n < 0){
            perror("error");
            return 1;
        }
        printf("%d\n", n);
        buf[n]=0;
        printf("buf %s\n", buf);
        sleep(2);
    }
    return 0;
}

a.txt 只有一个字符:

a

【问题讨论】:

  • 我认为您需要展示您正在使用的代码。如果您使用系统调用(read()write()truncate()open() 等)而不是标准 I/O 库调用(fread()getc()fopen() 等),您应该会看到由单独进程进行的截断立即生效。如果您的第一个程序(非截断程序)的读取位置为 1024 字节,但文件被截断,则下一次读取将返回 0(表示 EOF)。标准 I/O 库有缓冲;它可能不会立即发现截断。请创建一个 MCVE (minimal reproducible example) 来展示您的困惑。
  • StackOverflow 旨在帮助人们修复现有的编程代码。调试口头问题描述、教程、研究、工具、建议、库和代码的请求是题外话。 阅读stackoverflow.com/help/on-topicstackoverflow.com/help/how-to-askstackoverflow.com/help/dont-askstackoverflow.com/help/mcve,并在此处发布更多问题之前使用tour。祝你好运。
  • @Jonathan Leffler,shellter,对不起,我已经完成了代码,我很困惑为什么截断文件会立即影响读取过程?文件大小被缓存,它不会每次都立即从磁盘读取大小,为什么读取过程知道文件大小已更改?那么是内核通知打开文件的进程吗?
  • pluse-uno 用于包含一些代码,但您可能只需要接受“这就是它的工作方式”。在许多情况下,从另一个角度来看,这些问题可以解释为特征。 (严重地!) 。祝你好运!
  • @shellter,好的,非常感谢

标签: c linux


【解决方案1】:

缓存通常旨在提高性能,而不会产生任何其他可检测的影响。

如果进程缓存了 inode,正如您所描述的,那么具有缓存信息的进程可能看不到另一个进程所做的修改。那会很糟糕。

实际上,磁盘块被缓存,inode 被缓存,各种其他结构也可能被缓存,但在每种情况下,内核中都有一个缓存,所有进程共享,因此它们都有一致的视图。

当一个进程截断文件时,内存缓存会更新,存储新的文件大小(最终将写入磁盘,但可能不会立即写入)。当其他进程再次调用read 时,更新后的文件大小是从内存缓存中读取的,而不是从磁盘中读取的。

【讨论】:

  • 感谢您的回复,但是每个进程都缓存自己的inode,如果它们共享同一个inode,一个进程更改文件内容,另一个进程将可见。 unix环境下的高级编程也有图。就像这样!link
  • 图表中的所有内容都在内核内存中。 “进程表条目”是内核中的一个结构,表示内核对进程的了解。它包含指向打开文件表中条目的指针,其中包含指向 inode 的指针(我不知道这个 vnode 的东西......这是 BSD 术语,不适用于 Linux)。可以有来自不同进程的多个指针指向同一事物。同一时间在内存中永远不会有超过一份相同的 inode 副本。
  • 如果内核在内存中只有一个同一个inode的副本,为什么我修改文件内容,然后在终端用vim wq,读进程读不到改的?
  • 对不起,@Wumpus Q. Wumbley,我混淆了 inode 和数据块,所以数据块可能在内核中缓存了多个副本?
  • 我明白了,vim不会直接写入文件,1.将缓冲区写入新文件2.删除原文件3.重命名新文件
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多