C sur amd64 Linux, 36 octets (horodatage uniquement), 52 49 octets (activité réelle du disque)
Je code en dur les open(2)
drapeaux, donc ce n'est pas portable pour les autres ABI. Linux sur d'autres plates-formes utilise probablement la même chose O_TRUNC
, etc., mais pas les autres systèmes d'exploitation POSIX.
+4 octets pour passer un argument d'autorisation correct afin de vous assurer que le fichier est créé avec un accès en écriture propriétaire, voir ci-dessous. (Ceci arrive avec gcc 5.2)
ANSI C relativement portable, 38/51 octets (horodatage uniquement), 52/67 octets (activité réelle du disque)
Basé sur la réponse de @Chat, avec un conseil de @Jens.
Le premier nombre est destiné aux implémentations dans lesquelles une valeur int
peut être FILE *fopen()
retournée, le deuxième nombre si nous ne pouvons pas le faire. Sous Linux, il se trouve que les adresses de segment de mémoire se situent dans les 32 bits d'espace disque, de sorte que cela fonctionne même sans -m32
ou -mx32
. (Déclarer void*fopen();
est plus court que #include <stdio.h>
)
Métadonnées d'horodatage I / O uniquement :
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"));}
Écrire un octet, frapper le disque sous Linux 4.2.0 + XFS + lazytime
:
main(){for(;write(open("a",577),"",1);close(3));}
write
est la condition de boucle for, ce qui est correct car elle renvoie toujours 1. close
est l'incrément.
// 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
Explication de la version non portable:
Le fichier est créé avec des autorisations aléatoires. Avec gcc
5.2, avec -O0
ou -O3
, il arrive que l’autorisation d’écriture du propriétaire soit incluse, mais cela n’est pas garanti. 0666
est un nombre décimal 438. Un 3ème argument open
prendrait encore 4 octets . Nous sommes déjà en train de coder en dur O_TRUNC, etc., mais cela pourrait rompre avec un compilateur ou une libc différent sur le même ABI.
Nous ne pouvons pas omettre le 2nd argument open
, car la valeur de garbage inclut O_EXCL
, et O_TRUNC|O_APPEND
donc, open échoue avec EINVAL
.
Nous n'avons pas besoin de sauvegarder la valeur de retour de open()
. Nous supposons que c'est 3
parce que ça le sera toujours. Même si nous commençons par ouvrir fd 3, il sera fermé après la première itération. Dans le pire des cas, open
continue d'ouvrir de nouveaux fichiers jusqu'à ce que 3 soit le dernier descripteur de fichier disponible. Ainsi, jusqu'aux premiers 65531 write()
appels pourraient échouer avec EBADF
, mais fonctionneront ensuite normalement avec chaque open
création fd = 3.
577 = 0x241 = O_WRONLY|O_CREAT|O_TRUNC
sous Linux x86-64. Sans cela O_TRUNC
, le temps d'inode mod et le temps de changement ne sont pas mis à jour, donc un argument plus court n'est pas possible. O_TRUNC
est toujours essentiel pour la version qui appelle write
pour générer une activité de disque réelle et non pour réécrire en place.
Je vois des réponses qui open("a",1)
. O_CREAT est requis s'il a
n'existe pas déjà. O_CREAT
est défini comme octal 0100 (64, 0x40) sous Linux.
Aucune ressource ne fuit, elle peut donc fonctionner pour toujours. strace
sortie:
open("a", O_WRONLY|O_CREAT|O_TRUNC, 03777762713526650) = 3
close(3) = 0
... repeating
ou
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
J'ai eu la valeur décimale des open
drapeaux pour cette ABI en utilisant strace -eraw=open
ma version C ++.
Sur un système de fichiers avec l' lazytime
option de montage Linux activée, une modification qui affecte uniquement les horodatages d'inode ne provoquera qu'une écriture par 24 heures. Avec cette option de montage désactivée, la mise à jour d'horodatage peut constituer un moyen viable d'user votre disque SSD. (Cependant, plusieurs autres réponses ne font que des métadonnées d'E / S).
alternatives:
plus court non-travail :
main(){for(;;)close(write(open("a",577),"",3));}
utilise write
la valeur de retour pour passer un 3
argument à fermer. Il enregistre un autre octet, mais ne fonctionne pas avec gcc -O0 ou -O3 sur amd64. La poubelle du 3ème argument open
est différente et n'inclut pas l'autorisation d'écriture. a
est créé la première fois, mais les itérations futures échouent -EACCESS
.
plus long, fonctionnel, avec différents appels système :
main(c){for(open("a",65);pwrite(3,"",1);)sync();}
réécrit un octet sur place et appelle sync()
à synchroniser tous les systèmes de fichiers à l'échelle du système. La lumière de lecteur reste allumée.
Nous ne nous soucions pas de quel octet, nous ne passons donc pas le 4ème argument à écrire. Yay pour les fichiers clairsemés:
$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a
Écrire un octet avec un décalage de ~ 128 To a conduit xfs à utiliser 300 ko d'espace pour contenir la carte d'étendue, je suppose. N'essayez pas ceci sur OS X avec HFS +: IIRC, HFS + ne supporte pas les fichiers fragmentés, il va donc remplir le disque.
XFS est un système de fichiers 64 bits approprié, prenant en charge des fichiers individuels allant jusqu'à 8 exaoctets . c'est-à-dire 2 ^ 63-1, la valeur maximale off_t
peut être retenue.
strace
sortie:
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
? (Uneyes>/dev/null
réponse Bash est -elle valide?)