ขอผมทำลายมันหน่อย
เมื่อคุณเรียกใช้ไฟล์ปฏิบัติการลำดับของการเรียกระบบจะถูกดำเนินการโดยเฉพาะอย่างยิ่งfork()
และexecve()
:
fork()
สร้างกระบวนการลูกของกระบวนการเรียกซึ่งเป็นสำเนา (ส่วนใหญ่) ของพาเรนต์ที่แน่นอนทั้งสองยังคงเรียกใช้ไฟล์ปฏิบัติการเดียวกัน (โดยใช้เพจหน่วยความจำแบบคัดลอกตามการเขียนดังนั้นจึงมีประสิทธิภาพ) มันส่งคืนสองครั้ง: ในพาเรนต์จะส่งคืน PID ลูก ใน child มันจะคืนค่า 0 โดยปกติกระบวนการ child เรียก execve ทันที:
execve()
ใช้เส้นทางแบบเต็มไปยังไฟล์ที่เรียกทำงานได้เป็นอาร์กิวเมนต์และแทนที่กระบวนการเรียกด้วยไฟล์ปฏิบัติการ ณ จุดนี้กระบวนการที่สร้างขึ้นใหม่จะได้รับพื้นที่ที่อยู่เสมือนของตนเองเช่นหน่วยความจำเสมือนและการดำเนินการเริ่มต้นที่จุดเริ่มต้น (ในสถานะที่ระบุโดยกฎของแพลตฟอร์ม ABI สำหรับกระบวนการใหม่)
ณ จุดนี้โหลดเดอร์ของเคอร์เนล ELF ได้แมปข้อความและส่วนข้อมูลของปฏิบัติการลงในหน่วยความจำราวกับว่ามันได้ใช้การmmap()
เรียกของระบบ (ที่มีการแมปแบบอ่านอย่างเดียวและการอ่านเขียนส่วนตัวร่วมกันตามลำดับ) BSS นั้นจะถูกแมปเหมือนกับ MAP_ANONYMOUS (BTW ฉันไม่สนใจการเชื่อมโยงแบบไดนามิกที่นี่เพื่อความเรียบง่าย: ตัวเชื่อมโยงแบบไดนามิกopen()
และmmap()
ห้องสมุดแบบไดนามิกทั้งหมดก่อนที่จะข้ามไปยังจุดเข้าใช้งานของโปรแกรมหลัก
มีเพียงไม่กี่หน้าเท่านั้นที่ถูกโหลดเข้าสู่หน่วยความจำจากดิสก์ก่อนที่ผู้บริหารใหม่ () จะเริ่มเรียกใช้โค้ดของตนเอง หน้าต่อไปมีความต้องการเพจตามที่จำเป็นถ้า / เมื่อกระบวนการสัมผัสส่วนเหล่านั้นของพื้นที่ที่อยู่เสมือนของมัน (การโหลดหน้าใด ๆ ของรหัสหรือข้อมูลก่อนที่จะเริ่มดำเนินการรหัสพื้นที่ผู้ใช้เป็นเพียงการเพิ่มประสิทธิภาพ)
ไฟล์เรียกทำงานถูกระบุโดย inode ที่ระดับต่ำกว่า หลังจากไฟล์เริ่มทำงานเอ็มดีเคอร์นัลจะเก็บเนื้อหาของไฟล์ไว้โดยการอ้างอิง inode ไม่ใช่โดยชื่อไฟล์เช่นสำหรับตัวอธิบายไฟล์แบบเปิดหรือการแม็พหน่วยความจำที่สำรองไฟล์ไว้ ดังนั้นคุณสามารถย้ายไฟล์ปฏิบัติการไปยังตำแหน่งอื่นของระบบไฟล์หรือแม้กระทั่งบนระบบไฟล์อื่นได้อย่างง่ายดาย ในฐานะที่เป็นบันทึกด้านข้างเพื่อตรวจสอบสถิติต่างๆของกระบวนการคุณสามารถมองเข้าไปใน/proc/PID
ไดเรกทอรี (PID คือ ID กระบวนการของกระบวนการที่กำหนด) คุณสามารถเปิดไฟล์ที่เรียกใช้/proc/PID/exe
งานได้แม้จะไม่ได้เชื่อมโยงจากดิสก์
ทีนี้เรามาดูการเคลื่อนที่:
เมื่อคุณย้ายไฟล์ภายในระบบไฟล์เดียวกันการเรียกใช้ระบบที่ถูกเรียกใช้rename()
งานซึ่งเพิ่งเปลี่ยนชื่อไฟล์เป็นชื่ออื่น inode ของไฟล์จะยังคงเหมือนเดิม
ในขณะที่ระบบไฟล์ต่างกันสองระบบเกิดขึ้นสองอย่าง:
rm
ที่จริงแล้วคือunlink()
การใช้ไฟล์ที่กำหนดจากแผนผังไดเรกทอรีดังนั้นการมีสิทธิ์ในการเขียนในไดเรกทอรีจะทำให้คุณมีสิทธิ์เพียงพอที่จะลบไฟล์ใด ๆ ออกจากไดเรกทอรีนั้น
ตอนนี้เพื่อความสนุกลองนึกภาพว่าจะเกิดอะไรขึ้นเมื่อคุณย้ายไฟล์ระหว่างสองไฟล์และคุณไม่ได้รับอนุญาตให้unlink()
ใช้ไฟล์จากแหล่งที่มา
ไฟล์จะถูกคัดลอกไปยังปลายทางในตอนแรก ( read()
, write()
) จากนั้นunlink()
จะล้มเหลวเนื่องจากการอนุญาตไม่เพียงพอ ดังนั้นไฟล์จะยังคงอยู่ในทั้งสองระบบไฟล์ !!