C на amd64 Linux, 36 байт (тільки часова мітка), 52 49 байт (реальна дискова активність)
Я жорстко open(2)
кодую прапори, тому це не переноситься для інших ABI. Linux на інших платформах, ймовірно, використовує те саме O_TRUNC
і т.д., але інші POSIX ОС можуть не використовувати.
+4 байти, щоб передати правильний аргумент дозволу, щоб переконатися, що файл створений з доступом до запису власника, див. Нижче. (Це трапляється для роботи з gcc 5.2)
кілька портативний ANSI C, 38/51 байт (лише часова мітка), 52/67 байт (реальна активність диска)
На основі відповіді @ Cat, з підказкою від @Jens.
Перше число - це для реалізацій, де int
може містити FILE *fopen()
зворотне значення, друге - якщо ми не можемо цього зробити. В Linux, купи купи містяться в 32 бітах адресного простору, тому він працює навіть без -m32
або -mx32
. (Декларування void*fopen();
коротше #include <stdio.h>
)
Тільки метадані вводу / виводу часових міток :
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. Третій аргумент open
займе ще 4 байти . Ми вже жорстко кодуємо O_TRUNC і так далі, але це може зламатися з іншим компілятором або libc на тому ж ABI.
Ми не можемо опустити другий аргумент open
, тому що значення сміття включає O_EXCL
, і O_TRUNC|O_APPEND
, таким чином, відкриті не вдається EINVAL
.
Нам не потрібно зберігати повернене значення від open()
. Ми припускаємо, що так 3
, тому що це завжди буде. Навіть якщо ми почнемо з fd 3 open, він буде закритий після першої ітерації. Найгірше - він open
відкриває нові FDS, поки 3 не буде останнім доступним дескриптором файлів. Отже, до перших 65531 write()
дзвінків може не вдатися EBADF
, але тоді вони працюватимуть нормально при кожному open
створенні fd = 3.
577 = 0x241 = O_WRONLY|O_CREAT|O_TRUNC
в Linux x86-64. Без цього O_TRUNC
, час модифікації inode та час зміни не оновлюються, тому коротший аргумент неможливий. O_TRUNC
є все ще важливим для версії, яка дзвонитьwrite
виробляти фактичну активність диска, а не переписувати на місці.
Я бачу деякі відповіді на це open("a",1)
. O_CREAT потрібен, якщо a
він ще не існує. O_CREAT
визначається як восьмеричний 0100 (64, 0x40) в Linux.
Жоден ресурс не протікає, тому він може працювати назавжди. 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
Я отримав десяткове значення open
прапорців для цього ABI, використовуючи strace -eraw=open
мою версію C ++.
У файловій системі з lazytime
увімкненою опцією кріплення Linux зміна, яка впливає лише на часові позначки inode, спричинить лише одне записування протягом 24 годин. Якщо ця опція монтажу відключена, оновлення часових позначок може бути корисним способом зносу вашого SSD. (Однак кілька інших відповідей мають лише метадані I / O).
альтернативи:
коротший непрацюючий :
main(){for(;;)close(write(open("a",577),"",3));}
використовує write
повернене значення для передачі 3
аргументу на закриття. Він зберігає інший байт, але не працює з gcc -O0 або -O3 на amd64. Сміття в третьому аргументі open
відрізняється, і не містить дозволу на запис. a
створюється вперше, але майбутні ітерації не вдається -EACCESS
.
довше, працюючи, з різними системними дзвінками :
main(c){for(open("a",65);pwrite(3,"",1);)sync();}
переписує байт на місці і дзвонить sync()
синхронізувати всі файлові системи в масштабах усієї системи. Це засвічує світло приводу.
Нам не байдуже, який байт, тому ми не передаємо четвертий аргумент у pwrite. Так, для розріджених файлів:
$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a
Написання одного байта зі зміщенням ~ 128TiB призвело до xfs, використовуючи простір 300кіБ для зберігання карти масштабу, я думаю. Не спробуйте це в OS X з HFS +: 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
дійсна відповідь Баша?)