C na amd64 Linux, 36 bajtów (tylko znacznik czasu), 52 49 bajtów (rzeczywista aktywność dysku)
open(2)Zaszyfrowałem flagi na stałe, więc nie jest to przenośne dla innych ABI. Linux na innych platformach prawdopodobnie używa tego samego O_TRUNCitp., Ale inne systemy POSIX mogą tego nie robić.
+4 bajty, aby przekazać poprawny argument uprawnień arg, aby upewnić się, że plik został utworzony z prawem do zapisu przez właściciela, patrz poniżej. (Tak się dzieje, że działa z gcc 5.2)
nieco przenośny ANSI C, 38/51 bajtów (tylko znacznik czasu), 52/67 bajtów (rzeczywista aktywność dysku)
Na podstawie odpowiedzi @ Cat z napisem @Jens.
Pierwszy numer dotyczy implementacji, w których intmoże przechowywać FILE *fopen()wartość zwracaną, drugi numer, jeśli nie możemy tego zrobić. W systemie Linux adresy stosu znajdują się w mniejszych 32 bitach przestrzeni adresowej, więc działa nawet bez -m32lub -mx32. (Deklaracja void*fopen();jest krótsza niż #include <stdio.h>)
Tylko metadane sygnatury czasowej we / wy :
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"));}
Zapisywanie bajtu, faktyczne uderzenie w dysk w systemie Linux 4.2.0 + XFS + lazytime:
main(){for(;write(open("a",577),"",1);close(3));}
writejest warunkiem pętli, co jest w porządku, ponieważ zawsze zwraca 1. closejest przyrostem.
// 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
Objaśnienie wersji nieprzenośnej:
Plik jest tworzony z losowymi uprawnieniami do śmieci. W wersji gcc5.2 z -O0lub -O3zdarza się, że zawiera on uprawnienia właściciela do zapisu, ale nie jest to gwarantowane. 0666jest dziesiętnym 438. Trzeci argument, openktóry zajmie kolejne 4 bajty . Jesteśmy już na sztywno kodować O_TRUNC i tak dalej, ale to może zepsuć się z innym kompilatorem lub libc na tym samym ABI.
Nie możemy pominąć drugiego argumentu open, ponieważ zdarza się, że wartość śmieci zawiera O_EXCL, a O_TRUNC|O_APPENDwięc otwieranie kończy się niepowodzeniem EINVAL.
Nie musimy zapisywać wartości zwracanej open(). Zakładamy, że tak 3, bo zawsze tak będzie. Nawet jeśli zaczniemy od fd 3 open, zostanie ono zamknięte po pierwszej iteracji. W najgorszym przypadku, openotwiera nowe fds, dopóki 3 nie będzie ostatnim dostępnym deskryptorem pliku. Tak więc, do pierwszych 65531 write()wywołań może się nie powieść EBADF, ale wtedy będzie działać normalnie z każdym opentworzeniem fd = 3.
577 = 0x241 = O_WRONLY|O_CREAT|O_TRUNCw systemie Linux x86-64. Bez O_TRUNCtego czas mod i-węzła i czas zmiany nie są aktualizowane, więc krótszy argument nie jest możliwy. O_TRUNCjest nadal niezbędny dla wersji, która wywołuje writerzeczywistą aktywność dysku, a nie przepisuje w miejscu.
Widzę kilka odpowiedzi na to open("a",1). O_CREAT jest wymagany, jeśli jeszcze anie istnieje. O_CREATjest zdefiniowany jako ósemkowy 0100 (64, 0x40) w systemie Linux.
Brak wycieków zasobów, dzięki czemu może działać wiecznie. stracewynik:
open("a", O_WRONLY|O_CREAT|O_TRUNC, 03777762713526650) = 3
close(3) = 0
... repeating
lub
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
Mam wartość dziesiętną openflag dla tego ABI, używając strace -eraw=openmojej wersji C ++.
W systemie plików z lazytimewłączoną opcją montowania Linuksa zmiana, która wpływa tylko na znaczniki czasu i-węzła, spowoduje tylko jeden zapis na 24 godziny. Po wyłączeniu tej opcji montowania aktualizacja znaczników czasu może być dobrym sposobem na zużycie dysku SSD. (Jednak kilka innych odpowiedzi dotyczy tylko metadanych I / O).
alternatywy:
krótszy niedziałający :
main(){for(;;)close(write(open("a",577),"",3));}używa writewartości zwracanej do przekazania 3argumentu do zamknięcia. Zapisuje kolejny bajt, ale nie działa z gcc -O0 lub -O3 na amd64. Śmieci w trzecim arg opensą różne i nie obejmują uprawnień do zapisu. azostanie utworzony za pierwszym razem, ale wszystkie przyszłe iteracje kończą się niepowodzeniem -EACCESS.
dłużej, działając, z różnymi wywołaniami systemowymi :
main(c){for(open("a",65);pwrite(3,"",1);)sync();} przepisuje bajt w miejscu i wywołuje sync()synchronizację wszystkich systemów plików w całym systemie. Dzięki temu świeci lampka napędu.
Nie obchodzi nas, który bajt, więc nie przekazujemy czwartego argumentu do napisania. Tak, dla rzadkich plików:
$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a
Napisanie jednego bajtu z przesunięciem ~ 128TiB doprowadziło do XFS przy użyciu 300kB miejsca do przechowywania mapy zasięgu, tak myślę. Nie próbuj tego w systemie OS X z HFS +: IIRC, HFS + nie obsługuje plików rzadkich, więc zapełni dysk.
XFS to właściwy 64-bitowy system plików, obsługujący pojedyncze pliki do 8 eksabajtów . tj. 2 ^ 63-1, maksymalna wartość off_tmoże utrzymać.
strace wynik:
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? (Czyyes>/dev/nullważna jest odpowiedź Basha?)