在amd64 Linux上为C,36字节(仅时间戳),52 49字节(实际磁盘活动)
我对这些open(2)
标志进行了硬编码,因此它不能移植到其他ABI。其他平台上的Linux可能使用相同的O_TRUNC
,等等,但其他POSIX操作系统则可能不使用。
+4个字节可传递正确的权限arg,以确保该文件具有所有者写访问权限,请参见下文。(这恰好适用于gcc 5.2)
稍微可移植的ANSI C,38/51字节(仅时间戳),52/67字节(实际磁盘活动)
基于@Cat的答案,并附有@Jens的提示。
第一个数字用于其中int
可以保存FILE *fopen()
返回值的实现,第二个数字用于无法实现的返回值。在Linux上,堆地址恰好在地址空间的低32位中,因此即使没有-m32
或也可以使用堆地址-mx32
。(声明void*fopen();
比短#include <stdio.h>
)
仅时间戳元数据I / O:
main(){for(;;)close(open("a",577));} // Linux x86-64
//void*fopen(); // compile with -m32 or -mx32 or whatever, so an int holds a pointer.
main(){for(;;)fclose(fopen("a","w"));}
写一个字节,实际上是在Linux 4.2.0 + XFS +上打磁盘lazytime
:
main(){for(;write(open("a",577),"",1);close(3));}
write
是for循环条件,因为它总是返回1.,所以很好 close
。
// semi-portable: storing a FILE* in an int. Works on many systems
main(f){for(;f=fopen("a","w");fclose(f))fputc(0,f);} // 52 bytes
// Should be highly portable, except to systems that require prototypes for all functions.
void*f,*fopen();main(){for(;f=fopen("a","w");fclose(f))fputc(0,f);} // 67 bytes
非便携式版本的说明:
该文件是使用随机垃圾回收权限创建的。在gcc
5.2中,使用-O0
或时-O3
,恰好包含所有者的写许可权,但这不能保证。 0666
是小数点438。 第3个arg要open
占用另外4个字节。我们已经在硬编码O_TRUNC,依此类推,但是在同一ABI上使用其他编译器或libc可能会中断此操作。
我们不能忽略第二个arg open
,因为垃圾值恰好包含了O_EXCL
和O_TRUNC|O_APPEND
,所以打开失败EINVAL
。
我们不需要保存来自的返回值open()
。我们假设它是3
,因为它永远是。即使我们从打开fd 3开始,也将在第一次迭代后将其关闭。最坏的情况是,open
不断打开新的fds,直到3是最后一个可用的文件描述符。因此,最多前65531个write()
调用可能会因失败EBADF
,但随后在每次open
创建fd = 3时都能正常工作。
O_WRONLY|O_CREAT|O_TRUNC
在x86-64 Linux上为577 = 0x241 = 。如果不使用O_TRUNC
,则不会更新inode的mod时间和更改时间,因此不可能使用更短的arg。 O_TRUNC
对于调用write
以产生实际磁盘活动而不是就地重写的版本而言,它仍然是必不可少的。
我看到一些答案open("a",1)
。如果a
还不存在,则需要O_CREAT 。 O_CREAT
在Linux上定义为八进制0100(64,0x40)。
没有资源泄漏,因此它可以永远运行。 strace
输出:
open("a", O_WRONLY|O_CREAT|O_TRUNC, 03777762713526650) = 3
close(3) = 0
... repeating
要么
open("a", O_WRONLY|O_CREAT|O_TRUNC, 01) = 3
write(3, "\0", 1) = 1 # This is the terminating 0 byte in the empty string we pass to write(2)
close(3) = 0
我在C ++版本上open
使用了此ABI 的标志的十进制值strace -eraw=open
。
在lazytime
启用了Linux 挂载选项的文件系统上,仅影响inode时间戳的更改只会导致每24小时写入一次。在禁用该安装选项的情况下,时间戳更新可能是磨损SSD的可行方法。(但是,其他几个答案仅适用于元数据I / O)。
备择方案:
较短的不工作时间:
main(){for(;;)close(write(open("a",577),"",3));}
使用write
的返回值传递3
arg来关闭。它保存了另一个字节,但不适用于amd64上的gcc -O0或-O3。第三个arg中的垃圾open
是不同的,并且不包含写许可权。 a
第一次创建,但以后的迭代都失败了-EACCESS
。
更长,可以使用不同的系统调用:
main(c){for(open("a",65);pwrite(3,"",1);)sync();}
就地重写一个字节,并调用sync()
以在系统范围内同步所有文件系统。这样可以使驱动器指示灯保持点亮状态。
我们不在乎哪个字节,因此我们不会将第4个arg传递给pwrite。是的,对于稀疏文件:
$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a
我猜想,以〜128TiB的偏移量写入一个字节会导致xfs使用300kiB的空间来保存范围图。不要在具有HFS +的OS X上尝试此操作:IIRC,HFS +不支持稀疏文件,因此它将填充磁盘。
XFS是一个适当的64位文件系统,最多支持8艾字节的单个文件。即2 ^ 63-1,最大值off_t
可以保持。
strace
输出:
open("a", O_WRONLY|O_CREAT, 03777711166007270) = 3
pwrite(3, "\0", 1, 139989929353760) = 1
sync() = 0
pwrite(3, "\0", 1, 139989929380071) = 1
sync() = 0
...
/dev/null
呢?(yes>/dev/null
有效的Bash答案吗?)