เขียนไฟล์ที่มีอยู่ใหม่เพื่อให้มันถูกแทนที่ด้วยเวอร์ชั่นใหม่แบบ atom เพียงครั้งเดียวเท่านั้น


18

ฉันจำได้ว่าอ่านที่ไหนสักแห่งที่เคยมีใน Unices บางวิธีที่จะเปิดไฟล์ที่มีอยู่สำหรับการเขียนด้วยค่าสถานะที่ขอให้เคอร์เนลใช้เวอร์ชั่นเก่า (สำหรับกระบวนการอื่น ๆ ที่เข้าถึงมันเพื่ออ่าน) จนกระทั่ง "ใหม่ "รุ่นเขียนอย่างสมบูรณ์ (ปิด fd) จากจุดที่ไฟล์ปรากฏเป็นรุ่นใหม่

กล่าวอีกนัยหนึ่งกระบวนการอื่นอาจเห็นเวอร์ชันเก่าหรือกระบวนการใหม่ไม่เคยเขียนไม่สมบูรณ์

ใครบางคนที่มีความรู้สามารถชี้ให้ฉันอ้างอิงได้หรือไม่?


ดูเหมือนว่าPlan 9อาจทำ แต่ไม่
Gilles 'หยุดความชั่วร้าย'

2
เสียงเหมือนไฟล์ -11ใน OpenVMS: "ทุกครั้งที่ไฟล์ถูกบันทึกแทนที่จะเขียนทับเวอร์ชันที่มีอยู่ไฟล์ใหม่ที่มีชื่อเหมือนกัน แต่จะมีการสร้างหมายเลขเวอร์ชันที่เพิ่มขึ้น"
Mat

ทำไมคุณถาม คุณต้องการฟังก์ชั่นนั้นหรือเป็นเพียงความอยากรู้อยากเห็น?
นิลส์

1
ฉันมีความสุขที่มีฟังก์ชั่นนั้นและฉันจำได้ว่าอ่านบางที่มันมีอยู่ ดังนั้นการผสมผสานระหว่างความต้องการและความอยากรู้อยากเห็น
eudoxos

ระบบ Unix ทั้งหมดอนุญาตสิ่งนี้ในลักษณะอื่น - สร้างไฟล์ใหม่ในไดเรกทอรีเดียวกันเติมเนื้อหาที่มีการเปลี่ยนแปลงและทำการเปลี่ยนชื่ออะตอมมิก สิ่งนี้มีราคาแพงกว่ามากสำหรับการเปลี่ยนแปลงเล็กน้อย แต่ทำงานได้
Netch

คำตอบ:


14

สิ่งที่คุณกำลังอธิบายฟังดูคล้ายกับการเปลี่ยนชื่อพื้นฐานในการเขียนทับไฟล์

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

การrenameเรียกระบบเป็นการดำเนินการแบบอะตอมมิก ดังนั้นในการทำเช่นนี้คุณจะสร้างไฟล์ใหม่ภายใต้ชื่ออื่นจากนั้นโทรrenameเพื่อเปลี่ยนชื่อไฟล์ชั่วคราวเป็นไฟล์ที่คุณต้องการแทนที่ เนื่องจากการดำเนินการเป็นแบบอะตอมไม่มีช่วงเวลาที่ไฟล์หาย มันเปลี่ยนจากไฟล์เก่าไปเป็นไฟล์ใหม่ทันที
โปรดทราบว่าไฟล์ชั่วคราวและไฟล์ที่ถูกแทนที่จะต้องอยู่ในจุดเชื่อมต่อเดียวกัน


คุณสามารถใช้งานได้ก็ต่อเมื่อโปรแกรมของคุณเขียนขึ้นมาโดยเฉพาะ ในกรณีนี้มันเป็นคุณสมบัติของระบบปฏิบัติการซึ่งแม้แต่โปรแกรมปกติก็ให้ความหมายเชิงอะตอมโดยอัตโนมัติ
eudoxos

1
@eudoxos ความคิดเห็นของคุณไม่สมเหตุสมผล คุณกำลังบอกว่าโปรแกรมจะต้องถูกเขียนขึ้นโดยเฉพาะเพื่อทำrenameสิ่งที่แลกเปลี่ยน แม้ว่าจะมีคุณลักษณะ 'OS' ดังที่คุณกำลังพูดถึงอยู่ แต่โปรแกรมก็ยังต้องถูกเขียนขึ้นเพื่อใช้ประโยชน์จากสิ่งนั้นเช่นกัน ความแตกต่างคืออะไร?
Patrick

มีความแตกต่างถ้าคุณผ่านการตั้งค่าสถานะ (อาจไม่สนับสนุน) ไปยังopensyscall หรือถ้าคุณต้องทำสิ่งที่คุณอธิบายด้วยมือ
eudoxos

โปรดทราบว่าสำหรับการเก็บรุ่นเก่าหรือรุ่นใหม่ที่เขียนไว้อย่างสมบูรณ์ในกรณีที่เกิดข้อขัดข้องคุณจำเป็นต้องซิงค์ไฟล์ใหม่ไปยังดิสก์ด้วย fsync หรือคล้ายกันเพิ่มเติม
ตำรา

@ textshell โดยไม่ต้องซิงค์คุณยังคงได้รับ atomicity แม้ว่า .... เพียงแค่ไม่คงทน ... ถูกต้องหรือไม่ ฉันไม่เข้าใจอาร์กิวเมนต์ที่goo.gl/qfQQfyในกรณีนี้ ในกรณีของฉันฉันมีระบบภายใต้ภาระมากและฉันต้องการหลีกเลี่ยงการล้างระบบไฟล์และฉันไม่สนใจว่าไฟล์ยังคงมีข้อผิดพลาด
wcochran

6

ตามที่Patrick เขียนวิธีปกติในการทำเช่นนี้คือการเขียนเวอร์ชันใหม่ไปยังไฟล์แยกต่างหากและเมื่อเสร็จสิ้นการเปลี่ยนชื่อเวอร์ชันใหม่ไปเป็นชื่อไฟล์เก่าเขียนทับมันแบบอะตอม การดำเนินการที่สองเรียกว่าการเขียนทับโดยการเปลี่ยนชื่อ

ตอนนี้การอ้างอิงบางส่วน:


man 3p renameบอกฉันว่าrenameมันเป็นอะตอมแน่นอนและฉันเดาว่ามันมีความหมายสำหรับระบบไฟล์ Linux ทั้งหมด และเมื่อฉันอ่านบทความแรกที่คุณเชื่อมโยงฉันยังคิดว่าการเปลี่ยนชื่อ Btrfs นั้นเป็นเรื่องเกี่ยวกับอะตอม
hagello

1

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

ในกรณีนี้หากไฟล์ถูกแก้ไขโดยหนึ่งกระบวนการและได้รับการเปิดโดยกระบวนการอื่นกระบวนการหลังจะ "ดู" เวอร์ชันที่ไม่ได้แก้ไข ( หรือ "เก่า" หากคุณต้องการ ) เวอร์ชันของไฟล์

แน่นอนข้างต้นเป็นทฤษฎีและขึ้นอยู่กับปัจจัยต่าง ๆ และฉันจะบอกว่าคาดเดาไม่ได้เพราะคุณไม่รู้ว่าเมื่อเคอร์เนลจะล้างหน้าสกปรก ตัวอย่างเช่นใน Linux ( ตามที่คุณสามารถอ่านได้ในส่วนที่ 15.3 ของการทำความเข้าใจกับเคอร์เนล Linux ) หน้าสกปรกจะถูกเขียนไปยังดิสก์ภายใต้เงื่อนไขต่อไปนี้:

  • แคชของหน้าเต็มเกินไปและจำเป็นต้องมีหน้ามากขึ้นหรือจำนวนหน้าสกปรกมีขนาดใหญ่เกินไป

  • เวลาผ่านไปนานเกินไปเนื่องจากหน้าเว็บสกปรก

  • กระบวนการร้องขอการเปลี่ยนแปลงที่รอดำเนินการทั้งหมดของอุปกรณ์บล็อกหรือไฟล์เฉพาะที่จะล้างข้อมูล ทำได้โดยเรียกใช้การเรียกระบบ sync (), fsync () หรือ fdatasync ()

คุณสมบัตินี้เป็นที่รู้จักกันในการใช้งานในระบบไฟล์ HFS +, XFS, Reiser4, ZFS, Btrfs และ ext4


2
สิ่งที่คุณอธิบายคือเทคนิคระบบไฟล์ซึ่งควรจะมองไม่เห็นจาก userspace (และไม่ได้ทำสิ่งที่คุณระบุ) บนระบบ POSIX (ไฟล์) (ดูที่การเขียน : "หากการอ่าน () ของข้อมูลไฟล์สามารถพิสูจน์ได้ ที่จะเกิดขึ้นหลังจากการเขียน () ของข้อมูลนั้นจะต้องสะท้อนให้เห็นถึงการเขียน () แม้ว่าการโทรจะทำโดยกระบวนการที่แตกต่างกัน ") กระบวนการอื่นจะไม่เห็นข้อมูลเก่า (บน POSIX)
Mat

ขอบคุณสำหรับการแก้ไข ฉันเดาว่าความเข้าใจของฉันเกี่ยวกับเทคนิคระบบไฟล์นี้ผิด
dkaragasidis

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