ขนาดของ stack และ heap ถูก จำกัด โดยระบบปฏิบัติการอย่างไร


21

หมายเหตุ : หากคุณต้องการพิจารณาระบบปฏิบัติการเฉพาะเพื่อให้สามารถตอบได้โปรดพิจารณา Linux

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

คำถามที่ 1 : ทำสแต็กและฮีปมีขีด จำกัด ขนาดคงที่ (เช่น 2 กิกะไบต์แต่ละตัว) หรือเป็นขีด จำกัด แบบไดนามิกนี้เปลี่ยนไปตามการจัดสรรหน่วยความจำในระหว่างการดำเนินการของโปรแกรม (เช่น 4 กิกะไบต์ทั้งหมดที่จะใช้โดย ทั้งสองอย่างดังนั้นหากโปรแกรมใช้สแต็คเพียงอย่างเดียวมันจะสามารถมีสแต็คที่มี 4 กิกะไบต์)

คำถามที่ 2 : กำหนดวงเงินอย่างไร มันเป็นหน่วยความจำแรมทั้งหมดที่มีอยู่ไหม?

คำถามที่ 3 : ส่วนข้อความ (รหัส) และส่วนข้อมูลมีข้อ จำกัด อย่างไร


คำตอบ:


23

มีการ จำกัด หน่วยความจำที่แตกต่างกันสอง ขีด จำกัด หน่วยความจำเสมือนและขีด จำกัด หน่วยความจำกายภาพ

หน่วยความจำเสมือน

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

หน่วยความจำเสมือนที่ว่างไม่ได้ถูกทำเครื่องหมายว่าสามารถใช้งานได้ในตอนแรก ในขณะที่ฮีปสามารถขยายไปยังหน่วยความจำที่มีอยู่ทั้งหมด แต่ระบบส่วนใหญ่จะไม่เติบโตโดยอัตโนมัติ IIRC ขีด จำกัด เริ่มต้นสำหรับสแต็กคือ 8MiB บน Linux และ 1MiB บน Windows และสามารถเปลี่ยนแปลงได้ในทั้งสองระบบ หน่วยความจำเสมือนยังมีไฟล์และฮาร์ดแวร์ที่แมปหน่วยความจำ

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

บนแพลตฟอร์ม 32 บิตจำนวนหน่วยความจำเสมือนทั้งหมดคือ 4GiB โดยปกติแล้วทั้ง Linux และ Windows จะสำรอง 1GiB ล่าสุดสำหรับเคอร์เนลให้พื้นที่ 3GiB ส่วนใหญ่แก่คุณ มีรุ่นพิเศษของ Linux ที่ไม่ได้จองอะไรให้เต็ม 4GiB มันจะมีประโยชน์สำหรับกรณีที่หายากของฐานข้อมูลขนาดใหญ่ที่ 1GiB ล่าสุดบันทึกวัน แต่สำหรับการใช้งานปกติมันจะช้าลงเล็กน้อยเนื่องจากการโหลดตารางหน้าเพิ่มเติม

บนแพลตฟอร์ม 64 บิตหน่วยความจำเสมือนคือ 64EiB และคุณไม่ต้องคิดเกี่ยวกับมัน

หน่วยความจำกายภาพ

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

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

นี่คือวิธีที่กระบวนการตายบน Android (ซึ่งก็คือ Linux) ตรรกะได้รับการปรับปรุงด้วยตรรกะซึ่งกระบวนการที่จะลบออกจากการมีชีวิตอยู่บนพื้นฐานของสิ่งที่กระบวนการทำและอายุเท่าไหร่ กว่า Android จะหยุดทำอะไร แต่นั่งอยู่ในพื้นหลังและ "out of memory killer" จะฆ่าพวกมันเมื่อมันต้องการหน่วยความจำสำหรับตัวใหม่


9

ฉันคิดว่าการตอบคำถามนี้ทำได้ง่ายขึ้นตามลำดับการใช้หน่วยความจำ

คำถามที่ 3: ส่วนข้อความ (รหัส) และส่วนข้อมูลมีข้อ จำกัด อย่างไร ข้อความและข้อมูลจัดทำโดยคอมไพเลอร์ ข้อกำหนดสำหรับคอมไพเลอร์คือการทำให้แน่ใจว่าพวกเขาสามารถเข้าถึงได้และแพ็คพวกเขาในส่วนที่อยู่ด้านล่าง พื้นที่ที่อยู่ที่เข้าถึงได้จะถูก จำกัด โดยฮาร์ดแวร์เช่นหากตัวชี้คำแนะนำการลงทะเบียนเป็น 32 บิตพื้นที่ที่อยู่ข้อความจะเป็น 4 GiB

คำถามที่ 2: กำหนดวงเงินอย่างไร มันเป็นหน่วยความจำแรมทั้งหมดที่มีอยู่ไหม? หลังจากข้อความและข้อมูลพื้นที่ด้านบนนั่นคือกอง ด้วยหน่วยความจำเสมือนฮีปสามารถเติบโตได้ใกล้เคียงกับพื้นที่แอดเดรสสูงสุด

คำถามที่ 1: ทำสแต็กและฮีปมีขีด จำกัด ขนาดคงที่ (เช่น 2 กิกะไบต์แต่ละตัว) หรือเป็นขีด จำกัด แบบไดนามิกนี้เปลี่ยนไปตามการจัดสรรหน่วยความจำในระหว่างการดำเนินการของโปรแกรม (เช่น 4 กิกะไบต์ทั้งหมดที่จะใช้โดย ทั้งสองอย่างดังนั้นหากโปรแกรมใช้สแต็คเพียงอย่างเดียวมันจะสามารถมีสแต็คที่มี 4 กิกะไบต์) เซ็กเมนต์สุดท้ายในพื้นที่แอดเดรสกระบวนการคือสแต็ก สแต็คจะใช้เวลาส่วนท้ายของพื้นที่ที่อยู่และมันเริ่มต้นจากจุดสิ้นสุดและเติบโตลง

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

มีขีด จำกัด ที่กำหนดสำหรับฮีป (สแต็ค) สำหรับแต่ละกระบวนการที่จะเริ่มต้น ขีด จำกัด นี้สามารถเปลี่ยนแปลงได้ที่รันไทม์ (โดยใช้ brk () / sbrk ()) โดยทั่วไปสิ่งที่เกิดขึ้นคือเมื่อกระบวนการต้องการพื้นที่ฮีพมากขึ้นและพื้นที่ที่จัดสรรไม่เพียงพอไลบรารีมาตรฐานจะออกการเรียกไปยังระบบปฏิบัติการ ระบบปฏิบัติการจะจัดสรรหน้าซึ่งโดยปกติจะจัดการโดยไลบรารีผู้ใช้สำหรับโปรแกรมที่จะใช้ เช่นถ้าโปรแกรมต้องการ 1 KiB ระบบปฏิบัติการจะให้ 4 KiB เพิ่มเติมและไลบรารีจะมอบ 1 KiB ให้กับโปรแกรมและเหลือ 3 KiB สำหรับใช้เมื่อโปรแกรมถามอีกครั้งในครั้งถัดไป

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

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