Amd64 Linux'ta C, 36 bayt (yalnızca zaman damgası), 52 49 bayt (gerçek disk etkinliği)
open(2)
Bayrakları zor kodluyorum, bu yüzden diğer ABI'lara taşınabilir değil. Diğer platformlarda Linux muhtemelen aynı O_TRUNC
, vb kullanır , ancak diğer POSIX işletim sistemleri olmayabilir.
+4 bayt , dosyanın sahibinin yazma erişimiyle oluşturulduğundan emin olmak için doğru bir izin argümanı iletmek için aşağıya bakın. (Bu, gcc 5.2 ile çalışır)
biraz taşınabilir ANSI C, 38/51 bayt (yalnızca zaman damgası), 52/67 bayt (gerçek disk etkinliği)
@Jens'in cevabına göre @Jens'tan bir ipucu ile.
İlk sayı, bir int
kişinin FILE *fopen()
dönüş değerini tutabileceği uygulamalar için , bunu yapamazsak ikinci sayıdır. Linux'ta, yığın adresleri düşük 32 bit adres alanı içinde olur, bu yüzden -m32
ya da olmadan çalışır -mx32
. (Beyanı void*fopen();
daha kısa #include <stdio.h>
)
Yalnızca zaman damgası meta verileri G / Ç :
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"));}
Bir bayt yazmak, aslında Linux 4.2.0 + XFS + diskine basmaklazytime
:
main(){for(;write(open("a",577),"",1);close(3));}
write
for-loop koşulu, her zaman 1 döndürdüğü için gayet iyi close
. Artım.
// 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
Taşınabilir olmayan versiyonun açıklaması:
Dosya rasgele çöp izinleriyle oluşturulur. İle gcc
birlikte 5.2, -O0
veya -O3
, sahibi yazma izni dahil olur, ancak bu garanti edilmemektedir. 0666
ondalık: 438. Başka bir 4 byte alabilen üçüncü bir argümanopen
. Zaten O_TRUNC kodlaması yapıyoruz, ancak bu aynı ABI'da farklı bir derleyici veya libc ile bozulabilir.
2. argümanı atlayamayız open
, çünkü çöp değeri buna dahil olur O_EXCL
ve O_TRUNC|O_APPEND
açık bu nedenle başarısız olur EINVAL
.
Dönüş değerini kaydetmemize gerek yok open()
. Bunu varsayıyoruz 3
, çünkü her zaman olacak. Fd 3 open ile başlasak bile, ilk yinelemeden sonra kapanacaktır. En kötüsü open
, en son kullanılabilir dosya tanıtıcısı 3 olana kadar yeni fds açmaya devam ediyor. Böylece, ilk 65531'e kadar write()
çağrı başarısız olabilir EBADF
, ancak daha sonra her open
yaratmada normal olarak çalışacaktır fd = 3.
577 = 0x241 = O_WRONLY|O_CREAT|O_TRUNC
x86-64 Linux'ta. Olmadan O_TRUNC
, inode mod zamanı ve değişim zamanı güncellenmez, bu nedenle kısa bir argüman mümkün değildir. O_TRUNC
hala write
yerine oturtulmadan değil, gerçek disk etkinliği oluşturmaya çalışan sürüm için hala gereklidir .
Buna bazı cevaplar görüyorum open("a",1)
. Henüz mevcut değilse a
, O_CREAT gereklidir . O_CREAT
Linux'ta sekizlik 0100 (64, 0x40) olarak tanımlanmıştır.
Kaynak sızıntısı yok, bu yüzden sonsuza kadar çalışabilir. strace
çıktı:
open("a", O_WRONLY|O_CREAT|O_TRUNC, 03777762713526650) = 3
close(3) = 0
... repeating
veya
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
Ben C ++ sürümünde open
kullanarak bu ABI için bayrakların ondalık değerini aldım strace -eraw=open
.
Linux lazytime
mount seçeneğinin etkin olduğu bir dosya sisteminde , yalnızca inode zaman damgalarını etkileyen bir değişiklik 24 saatte yalnızca bir yazmaya neden olur. Bu takma seçeneği devre dışı bırakıldığında, zaman damgası güncellemesi SSD'nizi yıpratmanın uygun bir yolu olabilir. (Ancak, diğer bazı yanıtlar yalnızca meta veri G / Ç yapar).
alternatifler:
kısa olmayan çalışma :
main(){for(;;)close(write(open("a",577),"",3));}
Kapatılacak write
bir 3
argümanı iletmek için 'return' değerini kullanır . Başka bir bayttan tasarruf eder, ancak amd64'te gcc -O0 veya -O3 ile çalışmaz. 3. argümandaki çöpler open
farklıdır ve yazma izni içermez. a
ilk kez yaratıldı, ancak gelecekteki yinelemelerin hepsi başarısızlıkla sonuçlandı -EACCESS
.
daha uzun, çalışıyor, farklı sistem çağrılarıyla :
main(c){for(open("a",65);pwrite(3,"",1);)sync();}
yerinde bir bayt yazar ve sync()
tüm dosya sistemlerini sistem genelinde senkronize etmek için çağırır . Bu, sürüş ışığının yanmasını sağlar.
Hangi baytı umursamıyoruz, o yüzden 4. arg'ı yazmak için geçmiyoruz. Seyrek dosyalar için Yay:
$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a
Sanırım ~ 128 TB'lık bir ofsette bir bayt yazmak, genişlik haritasını tutmak için 300 kB'lik bir alan kullanan xfs'ye yol açtı. OS X'te HFS + ile deneme: IIRC, HFS + seyrek dosyaları desteklemediğinden diski doldurur.
XFS, 8 exabayta kadar tek tek dosyaları destekleyen uygun bir 64bit dosya sistemidir . yani 2 ^ 63-1, maksimum değer off_t
tutabilir.
strace
çıktı:
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
Geçerli bir Bash cevap mı?)