ในขณะที่คำถาม Stack Overflow ดูเหมือนจะเพียงพอในตอนแรกฉันเข้าใจจากความคิดเห็นของคุณว่าทำไมคุณยังคงมีข้อสงสัยเกี่ยวกับเรื่องนี้ สำหรับฉันนี่เป็นสถานการณ์ที่สำคัญอย่างยิ่งที่เกี่ยวข้องเมื่อระบบย่อย UNIX (กระบวนการและไฟล์) สื่อสารกัน
อย่างที่คุณอาจทราบแล้วว่าระบบ UNIX มักจะแบ่งออกเป็นสองระบบย่อย: ระบบย่อยของไฟล์และระบบย่อยของกระบวนการ ตอนนี้ยกเว้นว่าจะได้รับคำสั่งเป็นอย่างอื่นผ่านการเรียกของระบบเคอร์เนลไม่ควรมีระบบย่อยทั้งสองนี้มีปฏิสัมพันธ์กับคนอื่น มี แต่ข้อยกเว้น: โหลดของแฟ้มที่ปฏิบัติการเป็นกระบวนการฯภูมิภาคข้อความ แน่นอนหนึ่งอาจโต้แย้งว่าการดำเนินการนี้ยังถูกทริกเกอร์โดยการเรียกของระบบ ( execve
) แต่โดยทั่วไปจะรู้ว่าเป็นกรณีหนึ่งที่ระบบย่อยของกระบวนการทำให้การร้องขอโดยนัยไปยังระบบย่อยของไฟล์
เนื่องจากระบบย่อยของกระบวนการไม่มีวิธีจัดการไฟล์ (ไม่เช่นนั้นจะไม่มีจุดแบ่งทั้งสองอย่าง) จึงต้องใช้สิ่งที่ระบบย่อยของไฟล์ให้การเข้าถึงไฟล์ นอกจากนี้ยังหมายความว่าระบบย่อยกระบวนการจะถูกส่งไปยังสิ่งที่วัดได้ว่าระบบย่อยไฟล์ใช้เกี่ยวกับการแก้ไข / การลบไฟล์ ในประเด็นนี้ผมจะขอแนะนำให้อ่านคำตอบของกิลส์ไปนี้ U & L คำถาม ส่วนที่เหลือของคำตอบของฉันขึ้นอยู่กับคำตอบทั่วไปนี้จาก Gilles
สิ่งแรกที่ควรสังเกตคือภายในไฟล์สามารถเข้าถึงได้ผ่านinodesเท่านั้น หากเคอร์เนลได้รับเส้นทางขั้นตอนแรกของมันคือการแปลมันเป็น inode ที่จะใช้สำหรับการดำเนินการอื่น ๆ ทั้งหมด เมื่อกระบวนการโหลดไฟล์เรียกทำงานลงในหน่วยความจำจะทำผ่านไอโหนดซึ่งได้รับการจัดเตรียมโดยระบบย่อยไฟล์หลังจากแปลพา ธ Inodes อาจเชื่อมโยงกับหลาย ๆ ทาง (ลิงค์) และโปรแกรมอาจลบลิงค์ได้ ในการลบไฟล์และ inode ของไฟล์นั้น userland จะต้องลบลิงก์ที่มีอยู่ทั้งหมดไปยัง inode นั้นและตรวจสอบให้แน่ใจว่าไฟล์นั้นไม่ได้ใช้งานโดยสมบูรณ์ เมื่อตรงตามเงื่อนไขเหล่านี้เคอร์เนลจะลบไฟล์ออกจากดิสก์โดยอัตโนมัติ
หากคุณดูที่การแทนที่ส่วนที่ปฏิบัติการได้ในคำตอบของ Gilles คุณจะเห็นว่าขึ้นอยู่กับวิธีที่คุณแก้ไข / ลบไฟล์เคอร์เนลจะตอบสนอง / ปรับตัวแตกต่างกันตลอดเวลาผ่านกลไกที่ใช้ในระบบย่อยของไฟล์
- หากคุณลองใช้กลยุทธ์หนึ่ง ( เปิด / ตัดให้เป็นศูนย์ / เขียนหรือเปิด / เขียน / ตัดให้มีขนาดใหม่ ) คุณจะเห็นว่าเคอร์เนลไม่รบกวนการจัดการคำขอของคุณ คุณจะได้รับข้อผิดพลาด 26: ไฟล์ข้อความไม่ว่าง (
ETXTBSY
) ไม่มีผลกระทบใด ๆ
- หากคุณลองกลยุทธ์ที่สองขั้นตอนแรกคือการลบไฟล์ที่เรียกทำงานได้ของคุณ อย่างไรก็ตามเนื่องจากมันถูกใช้โดยกระบวนการระบบย่อยของไฟล์จะเริ่มทำงานและป้องกันไฟล์ (และ inode) จากการถูกลบออกจากดิสก์อย่างแท้จริง จากจุดนี้วิธีเดียวที่จะเข้าถึงเนื้อหาของไฟล์เก่าคือทำผ่าน inode ซึ่งเป็นสิ่งที่ระบบย่อยกระบวนการทำเมื่อใดก็ตามที่ต้องการโหลดข้อมูลใหม่ลงในส่วนข้อความ (ภายในไม่มีจุดใช้เส้นทางยกเว้น เมื่อแปลมันเป็นไอโหนด) แม้ว่าคุณจะยกเลิกการเชื่อมโยงแล้วก็ตามไฟล์ (ลบเส้นทางทั้งหมดของมัน) กระบวนการยังสามารถใช้งานได้ราวกับว่าคุณไม่ได้ทำอะไรเลย การสร้างไฟล์ใหม่ด้วยพา ธ เก่าจะไม่เปลี่ยนแปลงอะไรเลย: ไฟล์ใหม่จะได้รับไอโหนดใหม่อย่างสมบูรณ์ซึ่งกระบวนการทำงานไม่มีความรู้
กลยุทธ์ที่ 2 และ 3 มีความปลอดภัยสำหรับไฟล์ที่เรียกใช้งานเช่นกัน: แม้ว่าการเรียกใช้ไฟล์ปฏิบัติการ (และไลบรารีที่โหลดแบบไดนามิก) จะไม่เปิดไฟล์ในกรณีที่มีตัวให้คำอธิบายไฟล์ แต่จะทำงานในลักษณะเดียวกัน ตราบใดที่บางโปรแกรมกำลังรันโค้ดไฟล์จะยังคงอยู่บนดิสก์แม้ไม่มีรายการไดเรกทอรี
- กลยุทธ์ที่สามค่อนข้างคล้ายกันเนื่องจากการ
mv
ดำเนินการเป็นอะตอมมิก นี่อาจจะต้องใช้การrename
เรียกของระบบและเนื่องจากกระบวนการไม่สามารถถูกขัดจังหวะในขณะที่อยู่ในโหมดเคอร์เนลไม่มีอะไรสามารถรบกวนการดำเนินการนี้จนกว่าจะเสร็จสมบูรณ์ (สำเร็จหรือไม่) อีกครั้งไม่มีการเปลี่ยนแปลงของ inode ของไฟล์เก่า: อันใหม่ถูกสร้างขึ้นและกระบวนการที่รันอยู่แล้วจะไม่มีความรู้เกี่ยวกับมันแม้ว่ามันจะถูกเชื่อมโยงกับลิงค์อันใดอันหนึ่งของ inode เก่าก็ตาม
ด้วยกลยุทธ์ 3 ขั้นตอนในการย้ายไฟล์ใหม่ไปยังชื่อที่มีอยู่จะลบรายการไดเรกทอรีที่นำไปสู่เนื้อหาเก่าและสร้างรายการไดเรกทอรีที่นำไปสู่เนื้อหาใหม่ สิ่งนี้ทำในการปฏิบัติการแบบอะตอมเดียวดังนั้นกลยุทธ์นี้มีข้อได้เปรียบที่สำคัญ: หากกระบวนการเปิดไฟล์ได้ตลอดเวลาก็จะเห็นเนื้อหาเก่าหรือเนื้อหาใหม่ - ไม่มีความเสี่ยงในการผสมเนื้อหาหรือไฟล์ที่ไม่ได้ ที่มีอยู่.
การgcc
คอมไพล์ไฟล์อีกครั้ง : เมื่อใช้(และพฤติกรรมอาจคล้ายกันสำหรับคอมไพเลอร์อื่น ๆ ) คุณกำลังใช้กลยุทธ์ 2 คุณจะเห็นว่าโดยการเรียกใช้strace
กระบวนการของคอมไพเลอร์ของคุณ:
stat("a.out", {st_mode=S_IFREG|0750, st_size=8511, ...}) = 0
unlink("a.out") = 0
open("a.out", O_RDWR|O_CREAT|O_TRUNC, 0666) = 3
chmod("a.out", 0750) = 0
- คอมไพเลอร์ตรวจพบว่าไฟล์มีอยู่แล้วผ่านการเรียก
stat
และlstat
ระบบ
- ไฟล์จะถูกยกเลิกการเชื่อมโยง ที่นี่แม้ว่าจะไม่สามารถเข้าถึงได้ผ่านชื่ออีกต่อไป
a.out
ไอโหนดและเนื้อหาจะยังคงอยู่บนดิสก์ตราบใดที่มีการใช้งานโดยกระบวนการที่รันอยู่แล้ว
a.out
ไฟล์ใหม่จะถูกสร้างและทำให้ปฏิบัติการภายใต้ชื่อ นี่เป็นไอโหนดใหม่ล่าสุดและเนื้อหาใหม่ล่าสุดซึ่งกระบวนการที่รันอยู่แล้วไม่สนใจ
ตอนนี้เมื่อมันมาถึงไลบรารีที่ใช้ร่วมกันพฤติกรรมเดียวกันจะใช้ ตราบใดที่กระบวนการวัตถุไลบรารีใช้วัตถุนั้นจะไม่ถูกลบออกจากดิสก์ไม่ว่าคุณจะเปลี่ยนลิงค์ของมันอย่างไร เมื่อใดก็ตามที่มีสิ่งที่จะต้องโหลดลงในหน่วยความจำเคอร์เนลจะทำมันผ่านทาง inode ของไฟล์และจะละเว้นการเปลี่ยนแปลงที่คุณทำกับลิงค์ของมัน (เช่นการเชื่อมโยงพวกเขากับไฟล์ใหม่)