ไฟล์ต่อท้าย atomic ใน UNIX หรือไม่


107

โดยทั่วไปแล้วเราจะรับอะไรได้บ้างเมื่อเราผนวกเข้ากับไฟล์ใน UNIX จากกระบวนการต่างๆ เป็นไปได้ไหมที่จะสูญเสียข้อมูล (กระบวนการหนึ่งเขียนทับการเปลี่ยนแปลงของอีกฝ่าย)? เป็นไปได้ไหมที่ข้อมูลจะแหลกเหลว? (ตัวอย่างเช่นแต่ละกระบวนการต่อท้ายหนึ่งบรรทัดต่อการผนวกเข้ากับไฟล์บันทึกเป็นไปได้หรือไม่ที่สองบรรทัดจะยุ่งเหยิง) หากภาคผนวกไม่ใช่อะตอมตามความหมายข้างต้นวิธีใดที่ดีที่สุดในการรับประกันการยกเว้นซึ่งกันและกัน

คำตอบ:


65

การเขียนที่มีขนาดต่ำกว่า 'PIPE_BUF' ควรเป็นอะตอม ควรมีขนาดอย่างน้อย 512 ไบต์แม้ว่าจะมีขนาดใหญ่กว่าได้อย่างง่ายดาย (linux ดูเหมือนจะตั้งค่าเป็น 4096)

สมมติว่าคุณกำลังพูดถึงส่วนประกอบที่เข้ากันได้กับ POSIX ทั้งหมด ตัวอย่างเช่นสิ่งนี้ไม่เป็นความจริงบน NFS

แต่สมมติว่าคุณเขียนลงในไฟล์บันทึกที่คุณเปิดในโหมด "O_APPEND" และให้บรรทัดของคุณ (รวมถึงขึ้นบรรทัดใหม่) ภายใต้ไบต์ "PIPE_BUF" คุณควรมีผู้เขียนหลายคนในไฟล์บันทึกได้โดยไม่มีปัญหาความเสียหายใด ๆ การขัดจังหวะใด ๆ จะมาถึงก่อนหรือหลังการเขียนไม่ใช่ตรงกลาง หากคุณต้องการความสมบูรณ์ของไฟล์เพื่อให้รอดจากการรีบูตคุณจะต้องโทรหาfsync(2)ทุกครั้งหลังเขียน แต่มันแย่มากสำหรับประสิทธิภาพ

ชี้แจง : อ่านความคิดเห็นและคำตอบออนซ์โซโลมอน ฉันไม่แน่ใจว่าO_APPENDมันควรจะมีPIPE_BUFขนาดอะตอม เป็นไปได้ทั้งหมดว่าเป็นเพียงวิธีการใช้งาน Linux write()หรืออาจเป็นเพราะขนาดบล็อกของระบบไฟล์ที่อยู่เบื้องหลัง


11
ในระบบไฟล์ที่มีเหตุผลfsync(2)ให้การรับประกันมากพอ ๆ กับที่sync(2)ทำและไม่มีผลกระทบต่อประสิทธิภาพของค้อนขนาดใหญ่มากเท่า
ephemient

4
คุณแน่ใจหรือไม่? คุณช่วยให้ลิงค์เกี่ยวกับพฤติกรรมนั้นได้ไหม ฉันพบว่ามันได้รับการยืนยันแล้วว่า descriptor เป็นไปป์หรือไม่ แต่ฉันไม่พบหลักฐานว่ามันใช้ได้กับไฟล์ใด ๆ รวมถึงอ็อบเจ็กต์ไฟล์ปกติที่ไม่ใช่ NFS
Alan Franzoni

6
อยู่ที่ไหนกันแน่ใน ... / write.html? สำหรับ O_APPEND ฉันไม่เห็นการกล่าวถึง PIPE_BUF และฉันเห็นว่าสัญญาว่า"จะไม่มีการดำเนินการแก้ไขไฟล์แทรกแซงระหว่างการเปลี่ยนไฟล์ออฟเซ็ตและการดำเนินการเขียน"แต่ฉันไม่แน่ใจว่านี่หมายความว่าการดำเนินการเขียนเองหรือไม่ ไม่สะดุด ...
akavel

6
ในฐานะที่เป็นคำตอบนี้ชี้ให้เห็นคำสั่งเกี่ยวกับPIPE_BUFบนหน้าเว็บที่ใช้เฉพาะกับท่อและ FIFOs ไม่ไฟล์ปกติ
Greg Inozemtsev

3
กับสัญญาณที่จะมาถึงนี้จะได้รับแม้แต่เลว: bugzilla.kernel.org/show_bug.cgi?id=55651 เหตุใดสิ่งนี้จึงถูกระบุว่าเป็นคำตอบ PIPE_BUF ไม่มีส่วนเกี่ยวข้องกับไฟล์
ผอมบาง

35

แก้ไข:อัปเดตเมื่อสิงหาคม 2017 พร้อมผลลัพธ์ล่าสุดของ Windows

ฉันจะให้คำตอบพร้อมลิงก์สำหรับทดสอบโค้ดและผลลัพธ์ในฐานะผู้เขียนBoost.AFIO ที่เสนอซึ่งใช้ระบบไฟล์แบบอะซิงโครนัสและไลบรารีไฟล์ i / o C ++

ประการแรก O_APPEND หรือ FILE_APPEND_DATA ที่เทียบเท่าบน Windows หมายความว่าการเพิ่มขึ้นของขอบเขตไฟล์สูงสุด (ไฟล์ "ความยาว") เป็นแบบปรมาณูภายใต้การเขียนพร้อมกัน สิ่งนี้รับประกันโดย POSIX และ Linux, FreeBSD, OS X และ Windows ทั้งหมดใช้งานได้อย่างถูกต้อง Samba ยังดำเนินการอย่างถูกต้อง NFS ก่อน v5 ไม่ได้เนื่องจากไม่มีความสามารถในการจัดรูปแบบลวดในการผนวกอะตอม ดังนั้นหากคุณเปิดไฟล์ของคุณด้วยการผนวกเท่านั้นการเขียนพร้อมกันจะไม่ฉีกขาดซึ่งกันและกันในระบบปฏิบัติการหลักใด ๆเว้นแต่จะมี NFS เกี่ยวข้อง

อย่างไรก็ตามการอ่านพร้อมกันไปยังส่วนต่อท้ายของอะตอมอาจเห็นการเขียนขาด ๆ หาย ๆ ขึ้นอยู่กับระบบปฏิบัติการระบบการจัดเก็บข้อมูลและแฟล็กที่คุณเปิดไฟล์ด้วย - การเพิ่มขอบเขตไฟล์สูงสุดเป็นแบบอะตอม แต่การมองเห็นการเขียนที่เกี่ยวกับการอ่านอาจหรือไม่ก็ได้ เป็นปรมาณู นี่คือสรุปโดยย่อตามแฟล็กระบบปฏิบัติการและระบบการจัดเก็บ:


ไม่มี O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 พร้อม NTFS: อัปเดต atomicity = 1 ไบต์จนถึงและรวม 10.0.10240 จาก 10.0.14393 อย่างน้อย 1Mb อาจไม่มีที่สิ้นสุด (*)

Linux 4.2.6 พร้อม ext4: อัปเดต atomicity = 1 ไบต์

FreeBSD 10.2 พร้อม ZFS: อัปเดต atomicity = อย่างน้อย 1Mb อาจไม่มีที่สิ้นสุด (*)

O_DIRECT / FILE_FLAG_NO_BUFFERING:

Microsoft Windows 10 พร้อม NTFS: อัปเดต atomicity = จนถึงและรวม 10.0.10240 ได้ถึง 4096 ไบต์เฉพาะเมื่อจัดหน้าเท่านั้นมิฉะนั้น 512 ไบต์หากปิด FILE_FLAG_WRITE_THROUGH อื่น 64 ไบต์ โปรดทราบว่า atomicity นี้น่าจะเป็นคุณลักษณะของ PCIe DMA มากกว่าที่ออกแบบมาตั้งแต่ 10.0.14393 อย่างน้อย 1Mb อาจไม่มีที่สิ้นสุด (*)

Linux 4.2.6 พร้อม ext4: อัปเดต atomicity = อย่างน้อย 1Mb อาจไม่มีที่สิ้นสุด (*) โปรดทราบว่า Linux รุ่นก่อนหน้านี้ที่มี ext4 ไม่เกิน 4096 ไบต์แน่นอน XFS เคยมีการล็อกแบบกำหนดเอง แต่ดูเหมือนว่า Linux ล่าสุดได้แก้ไขสิ่งนี้แล้วในที่สุด

FreeBSD 10.2 พร้อม ZFS: อัปเดต atomicity = อย่างน้อย 1Mb อาจไม่มีที่สิ้นสุด (*)


ท่านสามารถเข้าดูผลการทดสอบเชิงประจักษ์ดิบที่https://github.com/ned14/afio/tree/master/programs/fs-probe โปรดทราบว่าเราทดสอบการฉีกขาดเฉพาะกับ 512 ไบต์ทวีคูณดังนั้นฉันไม่สามารถบอกได้ว่าการอัปเดตบางส่วนของภาค 512 ไบต์จะฉีกขาดในระหว่างรอบการอ่านแก้ไข - เขียน

ดังนั้นเพื่อตอบคำถามของ OP O_APPEND การเขียนจะไม่รบกวนกันและกัน แต่การอ่าน O_APPEND พร้อมกันอาจจะเห็นการเขียนแบบขาด ๆ หาย ๆ บน Linux ด้วย ext4 เว้นแต่ว่า O_DIRECT จะเปิดอยู่ซึ่งการเขียน O_APPEND ของคุณจะต้องมีขนาดเซกเตอร์หลายขนาด


(*) "อาจไม่มีที่สิ้นสุด" เกิดจากอนุประโยคเหล่านี้ในข้อมูลจำเพาะ POSIX:

ฟังก์ชันทั้งหมดต่อไปนี้จะเป็นแบบ atomic ซึ่งกันและกันในเอฟเฟกต์ที่ระบุใน POSIX.1-2008 เมื่อทำงานกับไฟล์ปกติหรือลิงก์สัญลักษณ์ ... [หลายฟังก์ชัน] ... read () ... write ( ) ... ถ้าสองเธรดแต่ละชุดเรียกใช้ฟังก์ชันเหล่านี้อย่างใดอย่างหนึ่งการเรียกแต่ละครั้งจะเห็นผลที่ระบุทั้งหมดของการเรียกอื่นหรือไม่มีเลย [ที่มา]

และ

การเขียนสามารถจัดลำดับตามการอ่านและเขียนอื่น ๆ หากข้อมูลไฟล์ read () สามารถพิสูจน์ได้ (ด้วยวิธีการใด ๆ ) ที่จะเกิดขึ้นหลังจากการ write () ของข้อมูลข้อมูลนั้นจะต้องแสดงถึง write () นั้นแม้ว่าจะมีการเรียกใช้โดยกระบวนการที่แตกต่างกันก็ตาม [ที่มา]

แต่ตรงกันข้าม:

ปริมาณ POSIX.1-2008 นี้ไม่ได้ระบุลักษณะการทำงานของการเขียนพร้อมกันไปยังไฟล์จากหลายกระบวนการ แอปพลิเคชันควรใช้รูปแบบการควบคุมการทำงานพร้อมกันบางรูปแบบ [ที่มา]

คุณสามารถอ่านเพิ่มเติมเกี่ยวกับความหมายของสิ่งเหล่านี้ได้ในคำตอบนี้


29

ฉันเขียนสคริปต์เพื่อทดสอบขนาดต่อท้ายอะตอมสูงสุดในเชิงประจักษ์ สคริปต์ที่เขียนด้วย bash สร้างกระบวนการของผู้ปฏิบัติงานหลายขั้นตอนซึ่งทั้งหมดจะเขียนลายเซ็นเฉพาะผู้ปฏิบัติงานลงในไฟล์เดียวกัน จากนั้นจะอ่านไฟล์โดยมองหาลายเซ็นที่ทับซ้อนกันหรือเสียหาย คุณสามารถดูแหล่งที่มาของสคริปต์ได้ที่โพสต์บล็อกนี้

ขนาดต่อท้ายอะตอมสูงสุดที่แท้จริงนั้นแตกต่างกันไปไม่เพียง แต่ตามระบบปฏิบัติการเท่านั้น แต่ตามระบบไฟล์

บน Linux + ext3 ขนาดคือ 4096 และบน Windows + NTFS ขนาดคือ 1024 ดูความคิดเห็นด้านล่างสำหรับขนาดเพิ่มเติม


คุณทดสอบระบบไฟล์ใดบน Linux ฉันสงสัยว่าอาจเป็นไปตามขนาดบล็อกระบบไฟล์
freiheit

@freiheit ฉันเชื่อว่าในเวลาที่ฉันทดสอบกับ ext3 หากคุณรันบน FS อื่นและได้ผลลัพธ์ที่แตกต่างออกไปโปรดโพสต์ความคิดเห็น
Oz Solomon

3
@OzSolomon ฉันใช้สคริปต์ของคุณบน Debian 7.8 และฉันสามารถเขียน atomic ได้สูงสุดและรวมถึง 1008 ไบต์ (1024 - 16 ไบต์ของค่าใช้จ่าย?) ทั้งบนพาร์ติชัน ext4 ของฉันและเมาท์ tmpfs สิ่งที่เกินกว่านั้นส่งผลให้เกิดการทุจริตทุกครั้ง
Eric Pruitt

6
การทดสอบของคุณดูเหมือนว่าecho $line >> $OUTPUT_FILEจะทำให้เกิดการโทรเพียงครั้งเดียวwriteโดยไม่คำนึงถึงขนาดของ$line.
Tomas

16

นี่คือสิ่งที่มาตรฐาน says: http://www.opengroup.org/onlinepubs/009695399/functions/pwrite.html

หากO_APPENDตั้งค่าแฟล็กสถานะไฟล์การชดเชยไฟล์จะถูกตั้งค่าไว้ที่ส่วนท้ายของไฟล์ก่อนการเขียนแต่ละครั้งและจะไม่มีการดำเนินการแก้ไขไฟล์แทรกระหว่างการเปลี่ยนออฟเซ็ตไฟล์และการดำเนินการเขียน


20
"ระหว่าง" - แต่สิ่งที่เกี่ยวกับการแทรกแซงในระหว่างการเขียนซึ่งสำหรับความเข้าใจของฉันเกิดขึ้นหลังจาก "ระหว่าง"? (เช่น: <change_offset_action> ... "the_between_period" ... <write_action>) - ฉันจะเข้าใจว่าไม่มีการรับประกันเกี่ยวกับเรื่องนี้หรือไม่?
akavel

@akavel เห็นด้วย; ไม่มีการรับประกันว่าสิ่งที่เขียนนั้นเป็นปรมาณู แต่ฉันสับสน: จากการรับประกันที่ให้ไว้ในใบเสนอราคาของคุณดูเหมือนว่าเราสามารถสรุปได้ว่าแอพมัลติเธรดที่ต่อท้ายไฟล์เดียวกันจะไม่ผสมส่วนของบันทึกที่เป็นลายลักษณ์อักษรต่างกัน อย่างไรก็ตามจากการทดลองที่รายงานโดย OzSolomon เราจะเห็นว่าแม้จะละเมิดข้อสันนิษฐานนั้น ทำไม?
สูงสุด

@max ขอโทษฉันกลัวว่าจะไม่ได้รับคำถามของคุณประการแรกการทดลองของ OzSolomon เป็นกระบวนการหลายขั้นตอนไม่ใช่แอปแบบมัลติเธรด (กระบวนการเดียว) ประการที่สองฉันไม่เข้าใจว่าคุณสรุปได้อย่างไรว่า"แอปมัลติเธรด [... ] จะไม่ผสม"นั่นคือสิ่งที่ฉันไม่เห็นว่าได้รับการรับรองจากคำพูดของบาสเตียนตามที่ฉันพูดถึงในความคิดเห็นของฉัน คุณสามารถชี้แจงคำถามของคุณได้หรือไม่?
akavel

2
อืมฉันไม่สามารถสร้างตรรกะของตัวเองขึ้นมาใหม่ได้ในขณะที่ฉันเขียนความคิดเห็นนั้น ... ใช่ถ้าการตีความของคุณถูกต้องแน่นอนว่าบันทึกที่แตกต่างกันอาจผสมกัน แต่ตอนนี้ฉันกำลังอ่านคำพูดของบาสเตียนฉันคิดว่ามันต้องหมายความว่าไม่มีใครสามารถขัดจังหวะ "ระหว่างการเขียน" ได้มิฉะนั้นทั้งย่อหน้าในมาตรฐานจะไร้ประโยชน์โดยไม่มีการรับประกันใด ๆ เลย (แม้การเขียนจะเกิดขึ้นก็ตาม ในตอนท้ายเนื่องจากบางครั้งอาจมีการย้ายออฟเซ็ตเนื่องจากขั้นตอน "เขียน" กำลังดำเนินการ
สูงสุด
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.