C บน amd64 Linux, 36 ไบต์ (เวลาประทับเท่านั้น), 52 49 ไบต์ (กิจกรรมบนดิสก์จริง)
ฉันเขียนโค้ดตั้งopen(2)
ค่าสถานะอย่างหนักดังนั้นจึงไม่สามารถพกพาไปยัง ABIs อื่น ๆ ได้ Linux บนแพลตฟอร์มอื่น ๆ อาจใช้แบบเดียวกันO_TRUNC
เป็นต้น แต่ POSIX OS อื่นอาจไม่รองรับ
+4 ไบต์เพื่อส่งผ่านสิทธิ์ที่ถูกต้องเพื่อให้แน่ใจว่าไฟล์ถูกสร้างขึ้นพร้อมสิทธิ์การเขียนของเจ้าของดูด้านล่าง (สิ่งนี้เกิดขึ้นกับ gcc 5.2)
ค่อนข้างพกพา ANSI C, 38/51 ไบต์ (เวลาประทับเท่านั้น), 52/67 ไบต์ (กิจกรรมบนดิสก์จริง)
ตามคำตอบของ @ Cat พร้อมด้วยคำแนะนำจาก @Jens
หมายเลขแรกสำหรับการใช้งานที่int
สามารถเก็บFILE *fopen()
ค่าส่งคืนของจำนวนที่สองถ้าเราไม่สามารถทำเช่นนั้น บน Linux, ที่อยู่กองเกิดขึ้นจะอยู่ในระดับต่ำ 32 บิตของพื้นที่ที่อยู่จึงทำงานได้โดยไม่ต้องหรือ-m32
-mx32
(การประกาศvoid*fopen();
สั้นกว่า#include <stdio.h>
)
ข้อมูลเมตาของ Timestamp 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-loop ซึ่งใช้ได้เนื่องจากมันส่งคืน 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 open
จะใช้เวลาอีก 4 ไบต์ เรากำลังเข้ารหัส O_TRUNC อย่างหนักอยู่แล้ว แต่สิ่งนี้อาจแตกต่างกับคอมไพเลอร์หรือ libc อื่นใน ABI เดียวกัน
เราไม่สามารถละเว้นหาเรื่องที่ 2 open
เพราะค่าขยะที่เกิดขึ้นที่จะรวมO_EXCL
และเปิดจึงล้มเหลวด้วยO_TRUNC|O_APPEND
EINVAL
open()
เราไม่จำเป็นต้องบันทึกค่าตอบแทนจาก เราถือว่ามันเป็น3
เพราะมันจะเป็น แม้ว่าเราเริ่มต้นด้วยการเปิด fd 3 มันจะถูกปิดหลังจากการทำซ้ำครั้งแรก กรณีที่เลวร้ายที่สุดopen
ยังคงเปิด fds ใหม่จนกระทั่ง 3 เป็นตัวบ่งชี้ไฟล์ล่าสุดที่มีอยู่ ดังนั้นการwrite()
โทรถึง65531 ครั้งแรกอาจล้มเหลวด้วยEBADF
แต่จะทำงานได้ตามปกติกับopen
การสร้างทุกfd = 3
577 = 0x241 = O_WRONLY|O_CREAT|O_TRUNC
บน x86-64 Linux หากไม่มีO_TRUNC
inode mod time และเวลาเปลี่ยนแปลงจะไม่ได้รับการอัพเดตดังนั้นจึงไม่สามารถหาเรื่องที่สั้นลงได้ 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 ขยะใน ARG ลำดับที่ 3 open
นั้นแตกต่างกันและไม่มีสิทธิ์ในการเขียน a
ได้รับการสร้างขึ้นเป็นครั้งแรก -EACCESS
แต่การทำซ้ำในอนาคตทั้งหมดล้มเหลวด้วย
อีกต่อไปทำงานด้วยการเรียกระบบที่แตกต่างกัน :
main(c){for(open("a",65);pwrite(3,"",1);)sync();}
เขียนไบต์แบบแทนที่และการโทรsync()
เพื่อซิงค์ระบบไฟล์ทั้งหมดทั่วทั้งระบบ นี่จะทำให้ไฟของไดรฟ์สว่างขึ้น
เราไม่สนใจว่าจะใช้ไบท์ไหนดังนั้นเราจึงไม่ผ่าน ARG ลำดับที่ 4 ไปยัง pwrite Yay สำหรับไฟล์ที่กระจัดกระจาย:
$ ll -s a
300K -rwx-wx--- 1 peter peter 128T May 15 11:43 a
การเขียนหนึ่งไบต์ที่ออฟเซ็ตของ ~ 128TiB นำไปสู่ xfs โดยใช้พื้นที่ 300kiB เพื่อเก็บแผนที่ขอบเขตฉันเดา อย่าลองทำสิ่งนี้ใน OS X ด้วย HFS +: IIRC, HFS + ไม่รองรับไฟล์ที่กระจัดกระจายดังนั้นมันจะเติมดิสก์
XFS เป็นระบบแฟ้ม 64bit เหมาะสมสนับสนุนแต่ละไฟล์ได้ถึง 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 ที่ถูกต้องหรือไม่)