copy-on-write in fork () จัดการหลาย fork อย่างไร


23

ตาม Wikipedia (ซึ่งอาจผิด)

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

ในกรณีเช่นนี้จะใช้เทคนิคที่เรียกว่า copy-on-write (COW) ด้วยเทคนิคนี้เมื่อมีการแยกหน้าเพจของกระบวนการหลักจะไม่ถูกคัดลอกสำหรับกระบวนการลูก แต่จะมีการแชร์หน้าระหว่างเด็กและกระบวนการหลักแทน เมื่อใดก็ตามที่กระบวนการ (พาเรนต์หรือชายด์) แก้ไขเพจสำเนาที่แยกต่างหากของเพจนั้นจะถูกสร้างขึ้นสำหรับกระบวนการนั้น (พาเรนต์หรือชายด์) ซึ่งดำเนินการแก้ไข กระบวนการนี้จะใช้เพจที่คัดลอกใหม่แทนที่จะเป็นเพจที่แชร์ในการอ้างอิงในอนาคตทั้งหมด กระบวนการอื่น (กระบวนการที่ไม่ได้แก้ไขเพจที่ใช้ร่วมกัน) ยังคงใช้สำเนาต้นฉบับของหน้าต่อไป (ซึ่งตอนนี้ไม่ได้ถูกแชร์อีกต่อไป) เทคนิคนี้เรียกว่า copy-on-write เนื่องจากหน้าจะถูกคัดลอกเมื่อบางกระบวนการเขียนไป

ดูเหมือนว่าเมื่อกระบวนการอย่างใดอย่างหนึ่งพยายามที่จะเขียนไปยังหน้าสำเนาใหม่ของหน้าได้รับการจัดสรรและกำหนดให้กับกระบวนการที่สร้างความผิดหน้า หน้าเดิมได้รับการทำเครื่องหมายว่าสามารถเขียนได้ในภายหลัง

คำถามของฉันคือจะเกิดอะไรขึ้นหากการfork()เรียกถูกเรียกหลายครั้งก่อนที่กระบวนการใด ๆ พยายามเขียนลงในเพจที่ใช้ร่วมกัน?


Wikipedia นั้นถูกต้องในกรณีนี้ระดับที่สูงขึ้นมาก
Didi Kohen

1
ใช่การคัดลอกเมื่อเขียนเป็นการทำสำเนาแบบขี้เกียจกระบวนการย่อยคัดลอกหน้าเมื่อพยายามเขียน โดยพื้นฐานแล้วหลังจากแยกแล้วหน่วยความจำของเด็กเกือบจะแชร์กับผู้ปกครอง อย่างไรก็ตามก่อนที่กระบวนการใด ๆ ที่ทำกระบวนการลูกทุกกระบวนการยังคงมีหน่วยความจำส่วนตัวบางส่วนแก้ไขจากการจัดสรรของผู้ปกครองหรือใหม่ ซึ่งหมายความว่าแม้ว่าจะไม่มีการดำเนินการใด ๆ ก็ตามกระบวนการลูกแบบแยกส่วนก็มีหน่วยความจำส่วนตัวบางส่วน เราสามารถตรวจสอบได้ด้วยหรือpmap -XX PID cat /proc/PID/smap
23

เกี่ยวกับ - "หน้าต้นฉบับได้รับการทำเครื่องหมายว่าสามารถเขียนได้ในภายหลัง" ใครจะเป็นเจ้าของ? นี่เป็นกระบวนการอื่นที่ยังไม่ได้ลองเขียนใช่ไหม
Adil

นี่มันช่างน่ารัก มาเริ่มสอนกันในโรงเรียนอนุบาล
ed22

คำตอบ:


18

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


ขวา. ประเด็นก็คือมันเป็นกระบวนการลูกที่มีความพิเศษที่มีหน้าที่ในการคัดลอกหากพยายามที่จะเขียนไปยังเพจที่ใช้ร่วมกัน ผู้ปกครองหรือเด็กคนอื่น ๆ ไม่จำเป็นต้องรู้เกี่ยวกับการเปลี่ยนแปลงหากทำอย่างถูกต้อง
Charles Stewart

9
กระบวนการลูกนั้นไม่พิเศษ ทั้งกระบวนการลูกและกระบวนการปกครองมีชุดของหน้าแบบอ่านอย่างเดียวหลังจากทางแยก เท่าที่หน้าเหล่านี้เกี่ยวข้องการจัดการหน้ามีความสมมาตร
jlliagre

3

พฤติกรรมของ fork () ขึ้นอยู่กับว่าระบบ * nix มี MMU หรือไม่ บนระบบที่ไม่ใช่ MMU (เช่น PDP-11s ก่อนหน้า) การเรียกระบบ fork () จะคัดลอกหน่วยความจำของผู้ปกครองทั้งหมดสำหรับเด็กแต่ละคน บนระบบ MMU ที่ใช้ * nix เคอร์เนลทำเครื่องหมายเพจที่ไม่ใช่สแต็กทั้งหมดเป็น R / O และแบ่งใช้ระหว่างพาเรนต์และชายด์ จากนั้นเมื่อกระบวนการใดประมวลผลไปยังหน้าใดเพจหนึ่ง MMU จะดักจับความพยายามเคอร์เนลจะจัดสรรหน้าที่เขียนได้และอัพเดตตารางเพจ MMU เพื่อชี้ไปยังเพจที่สามารถเขียนได้ในขณะนี้ ลักษณะการทำงานของการคัดลอกเมื่อเขียนนี้ให้ความเร็วขึ้นตั้งแต่เริ่มแรกจำเป็นต้องมีการจัดสรรและการสแต็กส่วนตัวสำหรับแต่ละกระบวนการย่อยเท่านั้น

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


0

เมื่อระบบ preforms fork โดยปกติ (ซึ่งอาจขึ้นอยู่กับการนำไปใช้) ระบบจะทำเครื่องหมายเพจเป็นแบบอ่านอย่างเดียวและทำเครื่องหมายกระบวนการหลักเป็นมาสเตอร์ของเพจเหล่านี้
เมื่อพยายามเขียนไปยังหน้าเหล่านี้จะเกิดความผิดพลาดของหน้าขึ้นและระบบปฏิบัติการจะเข้าแทนที่คัดลอกรายการทั้งหมดของหน้าหรือเพียงแค่การเปลี่ยนแปลง (อีกครั้งขึ้นอยู่กับการใช้งาน) ดังนั้นกระบวนการเขียนจะมีสำเนาที่เขียนได้
เมื่อมีหลายกระบวนการแยกจากกระบวนการเดียวกันเมื่อกระบวนการ "ต้นแบบ" เขียนไปยังหน่วยความจำของมันกระบวนการอื่น ๆจะได้รับหน้าที่คัดลอกเทียบเท่า


ระบบนี้ทำอะไร linux ใช้การนำไปใช้งานแบบคัดลอก - เขียน
brauliobo

นั่นคือวิธีการทำสำเนาการเขียน ...
Didi Kohen

3
@DavidKohen นั่นไม่ใช่วิธีการ copy-on-write ในเวอร์ชั่นใด ๆ ที่ฉันเคยได้ยิน ไม่มีกระบวนการ "ต้นแบบ" หากกระบวนการใด ๆเขียนเพจที่ใช้ร่วมกันสำเนานั้นจะถูกชนกับกระบวนการส่วนบุคคลในขณะที่กระบวนการอื่นทั้งหมดจะยังคงแชร์ต่อไป
Celada

1
ฉันคิดว่า David Kohen มีสิทธิ์ในบางประเด็น นี่เป็นวิธีหนึ่งในการนำ copy-on-write ไปใช้ ส่วนสำคัญจะเป็นที่มีการทำเครื่องหมายนี้การเขียนไปยังหน้านั้นจะก่อให้เกิดการจัดการข้อบกพร่องของหน้านั้นจะดำเนินการที่เหมาะสมเช่นการคัดลอกเมื่อเขียน น่าเสียดายที่รายละเอียดนี้ (ซึ่งจะเฉพาะระบบ) ส่วนใหญ่ไม่เกี่ยวข้องกับคำถาม โปรดทราบว่า CoW มีสองมิติ: สิ่งที่มองเห็นได้ในกระบวนการและหนึ่งในวิธีที่เคอร์เนลอาจนำไปใช้
0xC0000022L
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.