เมื่อกระบวนการใดคัดลอกหน่วยความจำเสมือนหรือหน่วยความจำในเครื่อง


12

วิธีมาตรฐานในการสร้างกระบวนการใหม่ใน Linux คือ footprint หน่วยความจำของกระบวนการหลักถูกคัดลอกและกลายเป็นสภาพแวดล้อมของกระบวนการลูกจนกว่าexecvจะมีการเรียกใช้

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

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

คำตอบ:


12

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

สิ่งนี้เรียกว่า copy-on-write

อย่างไรก็ตามอาจจำเป็นต้องติดตามพื้นที่ที่อยู่ที่กำหนดเช่นกัน หากไม่มีหน่วยความจำหรือการสลับในเวลาที่เคอร์เนลมีการคัดลอกหน้ามันจะต้องฆ่ากระบวนการบางอย่างเพื่อเพิ่มหน่วยความจำ สิ่งนี้ไม่เป็นที่ต้องการเสมอไปดังนั้นจึงเป็นไปได้ที่จะติดตามจำนวนหน่วยความจำที่เคอร์เนลกำหนด

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


1
If enough is available the kernel will commit to the full virtual size of the parent for both processes after the fork.ใช่ขอบคุณ. ความหมายที่ว่าการลดการปล่อยเสมือนจริงของกระบวนการในสภาพแวดล้อมที่มีหน่วยความจำที่ จำกัด (RAM และ swap) สามารถแก้ไขปัญหาที่ไม่สามารถแยกได้
TheMeaningfulEngineer

1
@ อลันใช่ หากforkล้มเหลวด้วยข้อความแสดงข้อผิดพลาดที่ระบุว่าหน่วยความจำไม่เพียงพอ จากนั้นลดการใช้หน่วยความจำเสมือนของกระบวนการก่อนการฟอร์กสามารถช่วยได้
kasperd

5

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

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

https://lwn.net/Articles/642202/


5

มีการตั้งค่าเคอร์เนล

proc / sys / / เมล์ / overcommit_memory

การอ้างอิงจากบทความที่ยอดเยี่ยม:

Since 2.5.30 the values are: 0 (default): as before: guess about how much  
overcommitment is reasonable, 1: never refuse any malloc(), 2: be precise 
about the overcommit - never commit a virtual address space larger than swap 
space plus a fraction overcommit_ratio of the physical memory. Here 
/proc/sys/vm/overcommit_ratio (by default 50) is another user-settable 
parameter. It is possible to set overcommit_ratio to values larger than 100. 
(See also Documentation/vm/overcommit-accounting.)

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

ในการแจกแจงส่วนใหญ่ฉันรู้ว่า overcommit คือ 0 แต่ถ้าคุณตั้งไว้ที่ 2 หน้าหน่วยความจำทั้งหมดจะได้รับการสนับสนุนอย่างเต็มที่จากหน่วยความจำจริงและในบางกรณีภายใต้ความกดดันหน่วยความจำสูงจะมีเสถียรภาพมากขึ้น เมื่อ overcommits จะล้มเหลว

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