จะเกิดอะไรขึ้นเมื่อไฟล์ที่เพจได้ 100% ในเพจแคชได้รับการแก้ไขโดยกระบวนการอื่น


14

ฉันรู้ว่าเมื่อมีการแก้ไขหน้าแคชหน้ามันมีการทำเครื่องหมายสกปรกและต้องมีการเขียนกลับ แต่สิ่งที่เกิดขึ้นเมื่อ

สถานการณ์จำลอง: ไฟล์ / apps / EXE ซึ่งเป็นไฟล์ที่เรียกทำงานได้ถูกทำเพจไว้ในแคชของเพจอย่างสมบูรณ์ (เพจทั้งหมดอยู่ในแคช / หน่วยความจำ) และถูกดำเนินการโดยกระบวนการ P

ปล่อยอย่างต่อเนื่องแล้วแทนที่ / apps / EXE ด้วยปฏิบัติการใหม่ล่าสุด

ข้อสันนิษฐานที่ 1: ฉันถือว่ากระบวนการ P (และทุกคนที่มีตัวอธิบายไฟล์ที่อ้างอิงถึงไฟล์ปฏิบัติการเก่า) จะยังคงใช้ไฟล์เก่าต่อไปในหน่วยความจำ / แอป / EXE โดยไม่มีปัญหาและกระบวนการใหม่ที่พยายามเรียกใช้เส้นทางนั้น ปฏิบัติการใหม่

ข้อสันนิษฐานที่ 2: ฉันสมมติว่าหากไม่มีการแมปหน้าไฟล์ทั้งหมดในหน่วยความจำสิ่งต่าง ๆ ก็จะถูกต้องจนกว่าจะมีข้อผิดพลาดของหน้าซึ่งต้องใช้หน้าจากไฟล์ที่ถูกแทนที่และอาจเป็น segfault หรือไม่

คำถามที่ 1: ถ้าคุณ mlock ทุกหน้าของไฟล์ด้วย vmtouch สิ่งนั้นเปลี่ยนแปลงสถานการณ์ได้หรือไม่?

คำถามที่ 2: หาก / apps / EXE อยู่ใน NFS ระยะไกลนั่นจะสร้างความแตกต่างหรือไม่? (ฉันคิดว่าไม่ได้)

โปรดแก้ไขหรือตรวจสอบสมมติฐาน 2 ข้อของฉันและตอบคำถาม 2 ข้อของฉัน

สมมติว่านี่เป็นกล่อง CentOS 7.6 ที่มีเคอร์เนล 3.10.0-957.el7 บางชนิด

อัปเดต: เมื่อพิจารณาเพิ่มเติมฉันสงสัยว่าสถานการณ์นี้จะไม่แตกต่างจากสถานการณ์หน้าสกปรกอื่น ๆ ..

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

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


เพียงเพื่อให้ชัดเจนการแทนที่ไฟล์จะไม่ใช่เรื่องใหญ่ (ขึ้นอยู่กับว่ามันถูกเปิดใหม่โดยแอปพลิเคชันและวิธีที่แอปพลิเคชันตอบสนองต่อเนื้อหาที่แก้ไข) แต่การแก้ไขไฟล์ mmaped อาจทำให้แอปพลิเคชันเสียหายรุนแรง ในโลกจาวาเมื่อไฟล์ zip ที่มีรายการไดเรกทอรี mmaped มีการเปลี่ยนแปลง) อย่างไรก็ตามมันขึ้นอยู่กับแพลตฟอร์ม แต่ไม่รับประกันว่าภูมิภาคที่มีรูปแบบ mmmm จะเห็นการเปลี่ยนแปลงหรือไม่
Eckes

คำตอบ:


12

ปล่อยอย่างต่อเนื่องแล้วแทนที่ / apps / EXE ด้วยปฏิบัติการใหม่ล่าสุด

นี่คือส่วนสำคัญ

วิธีการเปิดไฟล์ใหม่คือการสร้างไฟล์ใหม่ (เช่น/apps/EXE.tmp.20190907080000) การเขียนเนื้อหาการตั้งค่าการอนุญาตและความเป็นเจ้าของและในที่สุดก็เปลี่ยนชื่อ (2) เพื่อ/apps/EXEเปลี่ยนเป็นชื่อสุดท้ายแทนที่ไฟล์เก่า

ผลลัพธ์คือไฟล์ใหม่มีหมายเลขไอโหนดใหม่ (ซึ่งหมายความว่าเป็นไฟล์อื่น)

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

ที่สำคัญคือเมื่อเราพูดถึง "ไฟล์" ใน Linux เรามักพูดถึง "inodes" ตั้งแต่เปิดไฟล์ไฟล์ inode คือการอ้างอิงที่เราเก็บไว้ในไฟล์

ข้อสันนิษฐานที่ 1 : ฉันถือว่ากระบวนการ P (และทุกคนที่มีตัวอธิบายไฟล์ที่อ้างอิงถึงไฟล์ปฏิบัติการเก่า) จะยังคงใช้ไฟล์เก่าในหน่วยความจำ / แอป / EXE โดยไม่มีปัญหาและกระบวนการใหม่ใด ๆ ที่พยายามเรียกใช้เส้นทางนั้น ปฏิบัติการใหม่

แก้ไข.

ข้อสันนิษฐานที่ 2 : ฉันสมมติว่าหากไม่มีการแมปหน้าไฟล์ทั้งหมดในหน่วยความจำสิ่งต่าง ๆ ก็จะถูกต้องจนกว่าจะมีข้อผิดพลาดของหน้าซึ่งต้องใช้หน้าจากไฟล์ที่ถูกแทนที่และอาจเป็น segfault หรือไม่

ไม่ถูกต้อง ไอโหนดเก่ายังอยู่รอบ ๆ ดังนั้นข้อบกพร่องของเพจจากกระบวนการที่ใช้ไบนารีเก่าจะยังคงสามารถค้นหาเพจเหล่านั้นบนดิสก์ได้

คุณสามารถเห็นเอฟเฟกต์บางอย่างของสิ่งนี้ได้โดยดูที่/proc/${pid}/exesymlink (หรือเท่ากันlsofเอาท์พุท) สำหรับกระบวนการที่ใช้ไบนารีเก่าซึ่งจะแสดง/app/EXE (deleted)ให้เห็นว่าชื่อไม่ได้อยู่ที่นั่น แต่ inode ยังคงอยู่

คุณสามารถเห็นได้ว่า diskspace ที่ใช้โดยไบนารีจะได้รับการปล่อยตัวหลังจากกระบวนการตาย (สมมติว่าเป็นกระบวนการเดียวที่เปิด inode นั้น) ตรวจสอบผลลัพธ์ของdfก่อนและหลังการฆ่ากระบวนการคุณจะเห็นว่าขนาดลดลง ของไบนารีเก่าที่คุณคิดว่าไม่ได้อยู่อีกต่อไป

BTW นี่ไม่ได้มีเฉพาะกับไบนารีเท่านั้น แต่มีไฟล์ที่เปิดอยู่ หากคุณเปิดไฟล์ในกระบวนการและลบไฟล์ไฟล์นั้นจะถูกเก็บไว้ในดิสก์จนกว่ากระบวนการนั้นจะปิดไฟล์ (หรือตาย) ในทำนองเดียวกันกับวิธีที่ฮาร์ดลิงก์เก็บตัวนับจำนวนชื่อชี้ไปที่ไอโหนดในดิสก์ ไดรเวอร์ระบบไฟล์ (ในเคอร์เนล Linux) รักษาตัวนับจำนวนการอ้างอิงที่มีอยู่กับไอโหนดนั้นในหน่วยความจำและจะปล่อยไอโหนดจากดิสก์เมื่อการอ้างอิงทั้งหมดจากระบบที่ทำงานนั้นได้รับการเผยแพร่เช่นกัน

คำถามที่ 1 : ถ้าคุณ mlock ทุกหน้าของไฟล์ด้วย vmtouch สิ่งนั้นจะเปลี่ยนสถานการณ์

คำถามนี้ขึ้นอยู่กับข้อสันนิษฐานที่ไม่ถูกต้อง 2 ที่ไม่ได้ล็อคหน้าจะทำให้เกิด segfaults มันจะไม่

คำถามที่ 2 : หาก / apps / EXE อยู่ใน NFS ระยะไกลนั่นจะสร้างความแตกต่างหรือไม่? (ฉันคิดว่าไม่ได้)

มันหมายถึงการทำงานในลักษณะเดียวกันและใช้เวลาส่วนใหญ่ แต่ก็มี "gotchas" บางส่วนกับ NFS

บางครั้งคุณสามารถเห็นส่วนต่าง ๆ ของการลบไฟล์ที่ยังคงเปิดอยู่ใน NFS (แสดงเป็นไฟล์ที่ซ่อนอยู่ในไดเรกทอรีนั้น)

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

แต่แนวคิดหลักก็เหมือนกัน ไดรเวอร์ไคลเอนต์ NFS ยังคงใช้ inodes และจะพยายามเก็บไฟล์ไว้รอบ ๆ (บนเซิร์ฟเวอร์) ในขณะที่ inode นั้นยังคงอ้างอิงอยู่


1
การเปลี่ยนชื่อ (2) บล็อกจนกว่าจำนวนการอ้างอิงของไฟล์ oldname จะเป็นศูนย์หรือไม่?
เกร็ก Leventhal

2
ไม่เปลี่ยนชื่อ (2) จะไม่ปิดกั้น ไอโหนดเก่าจะถูกเก็บไว้เป็นเวลานาน
filbranden

1
ดูคำตอบของ @ mosvy เกี่ยวกับสาเหตุที่คุณไม่สามารถเขียนไฟล์ที่กำลังดำเนินการได้ (คุณได้รับ ETXTBSY) การยกเลิกการเชื่อมโยงและการสร้างใหม่มีผลเหมือนกันกับการเปลี่ยนชื่อ: คุณจะได้รับ inode ใหม่ (การเปลี่ยนชื่อดีกว่าเพราะไม่มีเวลาที่ชื่อไฟล์ไม่มีอยู่มันเป็นการดำเนินการปรมาณูแทนที่ชื่อให้ชี้ไปที่ inode ใหม่)
7324

4
@GreggLeventhal: "คุณกำลังทำอะไรเกี่ยวกับกระบวนการวางจำหน่ายอย่างต่อเนื่องที่ฉันใช้ซึ่งทำให้คุณแน่ใจว่ามันใช้ไฟล์ชั่วคราว" - เพราะตราบใดที่ Unix มีอยู่นั่นคือและเป็นวิธีเดียวที่จะทำ renameสวยมากเท่านั้นไฟล์และระบบแฟ้มการดำเนินงานที่รับประกันว่าจะเป็นอะตอม (สมมติว่าเราทำไม่ได้ข้ามระบบแฟ้มหรืออุปกรณ์เขตแดน) ดังนั้น "สร้างไฟล์ temp แล้วrename" เป็นรูปแบบมาตรฐานสำหรับการปรับปรุงไฟล์ นอกจากนี้ยังเป็นสิ่งที่ทุกโปรแกรมแก้ไขข้อความใน Unix ใช้เช่น
Jörg W Mittag

1
@ grahamj42: renameเป็นส่วนหนึ่งของ POSIX ได้รับมันถูกรวมไว้โดยอ้างอิงถึง ISO C (มาตรา 7.21.4.2 ในร่างปัจจุบัน) แต่มันอยู่ในนั้น
Jörg W Mittag

7

ข้อสันนิษฐานที่ 2: ฉันสมมติว่าหากไม่มีการแมปหน้าไฟล์ทั้งหมดในหน่วยความจำสิ่งต่าง ๆ ก็จะถูกต้องจนกว่าจะมีข้อผิดพลาดของหน้าซึ่งต้องใช้หน้าจากไฟล์ที่ถูกแทนที่และอาจเป็น segfault หรือไม่

ไม่นั่นจะไม่เกิดขึ้นเพราะเคอร์เนลจะไม่ให้คุณเปิดเขียนสิ่งใด ๆ ภายในไฟล์ที่ถูกเรียกใช้งานในปัจจุบัน การกระทำดังกล่าวจะล้มเหลวด้วยETXTBSY[1]:

cp /bin/sleep sleep; ./sleep 3600 & echo none > ./sleep
[9] 5332
bash: ./sleep: Text file busy

เมื่อ dpkg ฯลฯ อัพเดตไบนารีมันจะไม่เขียนทับมัน แต่ใช้rename(2)เพียงชี้รายการไดเรกทอรีไปยังไฟล์ที่แตกต่างอย่างสิ้นเชิงและกระบวนการใด ๆ ที่ยังคงมีการแมปหรือการจัดการเปิดไปยังไฟล์เก่าจะยังคงใช้งานได้โดยไม่มีปัญหา .

[1] การป้องกันดังกล่าวจะไม่ขยายไปยังไฟล์อื่นซึ่งสามารถพิจารณาได้ว่า "text" (live code / executable): shared library, java classes, ฯลฯ ; การแก้ไขไฟล์ดังกล่าวในขณะที่แมปโดยกระบวนการอื่นจะทำให้เกิดความผิดพลาด บน linux ตัวเชื่อมโยงแบบไดนามิกจะส่งผ่านMAP_DENYWRITEธงไปยังหน้าที่mmap(2)แต่ไม่ทำผิด - จะไม่มีผลใด ๆ


1
ในสถานการณ์ dpkg แล้วการเปลี่ยนชื่อเสร็จสมบูรณ์เมื่อใดดังนั้น dentry for / apps / EXE จะอ้างอิง inode ของไบนารีใหม่หรือไม่ เมื่อไม่มีการอ้างอิงถึงคนเก่าอีกแล้ว? มันทำงานอย่างไร
เกร็ก Leventhal

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

1
ฉันชอบคำตอบของคุณดีที่สุดเพราะการพูดถึง ETXTBSY ของคุณทำให้ฉันได้รับutcc.utoronto.ca/~cks/space/blog/unix/WhyTextFileBusyErrorนี้ซึ่งตอบคำถามของฉันทั้งหมด
เกร็ก Leventhal

4

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

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

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

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