当我截断正在使用的文件时会发生什么?

c4f4t0r

网上有很多人说您可以使用> filenametruncate -s0 filename在文件开始使用时截断文件

我知道每次进程在文件中写入数据时,该进程都会使用偏移量来写入文件,并使用类似的脚本进行测试。

#!/usr/bin/env python

import os, time

with open("passwd","w") as f: #copy of passwd file in my current directory
        f.seek(0)
        for x in xrange(1,1000):
                f.write("hello world \n" + time.ctime() + "\n")
                f.flush()
                time.sleep(2)

每次我的脚本进行系统调用时,/proc/pid_number/fdinfo/3 pos都会更改字段的偏移量,但是当我尝试使用上面列出的方法截断文件时,在我的文件中,^@当我使用vim或更少-u的文件打开文件时,会看到很多这样的字符,并且文件类型是从更改ASCII textdata,当我使用ls -l filename尺寸不变

因此,当截断文件时,文件的偏移量不会返回,我正在inCentos 7和in中对此进行测试Redhat 5,因此我可以知道在进程使用文件时更改文件的大小不会释放空间并使我的文件变脏。文件。

所以我的问题是,如果我的进程中有一个打开的文件,pos 1000而我确实有truncate -s0 filename,则如果截断有效,那么下一个进程中会发生什么?

strace truncate -s0 passwd
open("passwd", O_WRONLY|O_CREAT|O_NONBLOCK, 0666) = 3
ftruncate(3, 0)                         = 0
close(3)                                = 0
close(1)                                = 0
close(2)                                = 0
exit_group(0)                           = ?

 ls -l passwd 
 -rw-rw-r--. 1 user91 users 13832 Feb 23 17:16 passwd

如您所见,我的文件没有被截断

如果我以附加代码打开附加模式,则不会发生此问题。

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


int main(){
        int range = 1000;
        int x; x = open("passwd", O_WRONLY|O_CREAT|O_APPEND);
        int i = 0;
        for( i = 0; i <= range; range++)
                write(x,"hello world\n",12);
                sleep(2);
}
马修·艾夫(Matthew Ife)

请注意,尽管系统调用称为truncate,但实际上最好将其解释为“使我的文件报告这么多字节的大小”。根据系统调用手册页:

truncate()和ftruncate()函数使由path命名或由fd引用的常规文件被截断为恰好长度字节的大小。

如果该文件以前大于此大小,则多余的数据将丢失。如果该文件先前较短,则将其扩展,并且扩展部分读取为空字节('\ 0')。

因此,可以截断一个文件并使它更大而不是更小。

所以我的问题是,如果我的进程在pos 1000中有一个打开的文件,并且我确实截断了-s0文件名,如果截断有效,那么下一个进程中写的是什么?

  • 您已被截断。此阶段的文件大小为0字节。偏移量是1000。
  • 发生在位置1001的写入。
  • 文件大小为1002字节。字节0-1000包含'\ 0'(空)。字节1001+包含已写入的数据。

当您从大于文件本身的位置写入文件时,文件末尾与新写入之间的数据将变为空字节,并且这两点之间的文件数据被称为sparse

确实,您可以执行以下操作并产生相同的效果。

import os, sys

f = open('data.txt','w')
f.seek(1048576)
f.write('a')
f.flush()
f.close()

您还提到以附加模式打开可避免此行为。这是正确的,因为在这种情况下您正在指示内核“每次都写入文件的实际末尾”。如果截断,则文件末尾确实会更改。另外,您不能重新定位文件指针。

这是一个示例程序,演示了文件,偏移量和已被截断的文件中的数据将发生什么情况。

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

#define FPATH "/tmp/data.txt"
#define FSIZE 65536

int main() {
  int a,b;
  char buf[FSIZE];
  char byte;
  struct stat st;
  memset(buf, 'A', FSIZE);

  a = open(FPATH, O_WRONLY|O_CREAT);
  b = open(FPATH, O_RDONLY);

  if (a < 0 || b < 0)
    errx(EXIT_FAILURE, "Could not open file");

  printf("Writing %d * 'A' into file\n", FSIZE);
  /* Write some bytes */
  if(write(a, buf, FSIZE) != FSIZE)
    errx(EXIT_FAILURE, "Couldn't write complete size out");

  /* Seek to a  new position in the file */
  lseek(b, FSIZE/2, SEEK_SET);

  printf("Current position of handle 'a': %d\n", lseek(a, 0, SEEK_CUR));
  printf("Current position of handle 'b': %d\n", lseek(b, 0, SEEK_CUR));
  stat(FPATH, &st);
  printf("Reported size on filesystem of %s: %d\n", FPATH, st.st_size);

  /* OK -- now, read the byte at the position */
  if (read(b, &byte, 1) < 0)
    err(EXIT_FAILURE, "Could not read file");
  printf("Character at current position of handle 'b': '%c'\n", byte);

  /* Truncate the file in the 'a' handle */
  printf("Performing truncate...\n");
  if (ftruncate(a, 0) < 0)
    err(EXIT_FAILURE, "Cannot truncate file");

  printf("Current position of handle 'a': %d\n", lseek(a, 0, SEEK_CUR));
  printf("Current position of handle 'b': %d\n", lseek(b, 0, SEEK_CUR));
  stat(FPATH, &st);
  printf("Reported size on filesystem of %s: %d\n", FPATH, st.st_size);

  printf("Writing one byte via handle 'a'\n");
  if (write(a, buf, 1) < 0)
    err(EXIT_FAILURE, "Cannot perform second write");

  printf("Current position of handle 'a': %d\n", lseek(a, 0, SEEK_CUR));
  printf("Current position of handle 'b': %d\n", lseek(b, 0, SEEK_CUR));
  stat(FPATH, &st);
  printf("Reported size on filesystem of %s: %d\n", FPATH, st.st_size);

  if (read(b, &byte, 1) < 0)
    err(EXIT_FAILURE, "Could not read file");
  printf("Character at current position of handle 'b': '%c'\n", byte);


  close(a);
  close(b);
  exit(0);
}

结果为以下输出;

Writing 65536 * 'A' into file
Current position of handle 'a': 65536
Current position of handle 'b': 32768
Reported size on filesystem of /tmp/data.txt: 65536
Character at current position of handle 'b': 'A'
Performing truncate...
Current position of handle 'a': 65536
Current position of handle 'b': 32769
Reported size on filesystem of /tmp/data.txt: 0
Writing one byte via handle 'a'
Current position of handle 'a': 65537
Current position of handle 'b': 32769
Reported size on filesystem of /tmp/data.txt: 65537
Character at current position of handle 'b': ''

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

当我使用多个模拟时间时会发生什么?

来自分类Dev

当我使用多个模拟时间时会发生什么?

来自分类Dev

当我在Android中实例化文件时会发生什么?

来自分类Dev

当我绑定到AliasProperty时会发生什么?

来自分类Dev

当我调用“ BufferStrategy.show()”时会发生什么?

来自分类Dev

当我放弃对iOS 6的支持时会发生什么?

来自分类Dev

MySql-当我用“ and”更新时会发生什么

来自分类Dev

当我多次调用requestAnimationFrame时会发生什么

来自分类Dev

当我放弃对iOS 6的支持时会发生什么?

来自分类Dev

当我将%esp移至%ebp时会发生什么?

来自分类Dev

当我不输入期望的命令时会发生什么?

来自分类Dev

当我忘记登录TTY时会发生什么?

来自分类Dev

当我调用“ BufferStrategy.show()”时会发生什么?

来自分类Dev

当我取消订阅 Observable 链时会发生什么?

来自分类Dev

当我在Bash脚本中对函数使用`&`时会发生什么?

来自分类Dev

当我混合使用有符号和无符号类型时会发生什么?

来自分类Dev

当我在抽象方法上使用call_user_func()时会发生什么?

来自分类Dev

当我尝试使用进程ID小于-1的kill时会发生什么?

来自分类Dev

当我使用“ nmap google.com”命令时会发生什么?

来自分类Dev

当我在C ++中对类使用vector时会发生什么

来自分类Dev

当我使用“ dd”覆盖运行Ubuntu的磁盘时会发生什么?

来自分类Dev

在C ++中,当我对-128,127范围以外的整数使用static_cast <char>时会发生什么?

来自分类Dev

当我在同一指针中两次使用malloc()时会发生什么?

来自分类Dev

当我在先前定义的通过ajax调用的函数中使用相同的变量名时会发生什么?

来自分类Dev

当我将 System.Threading.Timer 与 TimerTrigger 一起使用时会发生什么?

来自分类Dev

当我以“ wb”模式写入文件时,会发生什么?

来自分类Dev

当我从RAM运行持久性存储实时USB时会发生什么情况?

来自分类Dev

就system_read中断,汇编而言,当我按Enter键时会发生什么?

来自分类Dev

当我包装两次I / O流时会发生什么?

Related 相关文章

  1. 1

    当我使用多个模拟时间时会发生什么?

  2. 2

    当我使用多个模拟时间时会发生什么?

  3. 3

    当我在Android中实例化文件时会发生什么?

  4. 4

    当我绑定到AliasProperty时会发生什么?

  5. 5

    当我调用“ BufferStrategy.show()”时会发生什么?

  6. 6

    当我放弃对iOS 6的支持时会发生什么?

  7. 7

    MySql-当我用“ and”更新时会发生什么

  8. 8

    当我多次调用requestAnimationFrame时会发生什么

  9. 9

    当我放弃对iOS 6的支持时会发生什么?

  10. 10

    当我将%esp移至%ebp时会发生什么?

  11. 11

    当我不输入期望的命令时会发生什么?

  12. 12

    当我忘记登录TTY时会发生什么?

  13. 13

    当我调用“ BufferStrategy.show()”时会发生什么?

  14. 14

    当我取消订阅 Observable 链时会发生什么?

  15. 15

    当我在Bash脚本中对函数使用`&`时会发生什么?

  16. 16

    当我混合使用有符号和无符号类型时会发生什么?

  17. 17

    当我在抽象方法上使用call_user_func()时会发生什么?

  18. 18

    当我尝试使用进程ID小于-1的kill时会发生什么?

  19. 19

    当我使用“ nmap google.com”命令时会发生什么?

  20. 20

    当我在C ++中对类使用vector时会发生什么

  21. 21

    当我使用“ dd”覆盖运行Ubuntu的磁盘时会发生什么?

  22. 22

    在C ++中,当我对-128,127范围以外的整数使用static_cast <char>时会发生什么?

  23. 23

    当我在同一指针中两次使用malloc()时会发生什么?

  24. 24

    当我在先前定义的通过ajax调用的函数中使用相同的变量名时会发生什么?

  25. 25

    当我将 System.Threading.Timer 与 TimerTrigger 一起使用时会发生什么?

  26. 26

    当我以“ wb”模式写入文件时,会发生什么?

  27. 27

    当我从RAM运行持久性存储实时USB时会发生什么情况?

  28. 28

    就system_read中断,汇编而言,当我按Enter键时会发生什么?

  29. 29

    当我包装两次I / O流时会发生什么?

热门标签

归档