ฉันสนใจความแตกต่างระหว่าง Highmem และ Lowmem:
- ทำไมถึงมีความแตกต่างเช่นนี้?
- เราได้อะไรจากการทำเช่นนั้น?
- แต่ละคุณสมบัติมีอะไรบ้าง
ฉันสนใจความแตกต่างระหว่าง Highmem และ Lowmem:
คำตอบ:
บนสถาปัตยกรรม 32 บิตช่วงพื้นที่ที่อยู่สำหรับการกำหนดแอดเดรส RAM คือ:
0x00000000 - 0xffffffff
หรือ4'294'967'295
(4 GB)
เคอร์เนล linux จะแยกออกเป็น 3/1 (อาจเป็น 2/2 หรือ 1/3 1 ) ในพื้นที่ผู้ใช้ (หน่วยความจำสูง) และพื้นที่เคอร์เนล (หน่วยความจำต่ำ) ตามลำดับ
ช่วงพื้นที่ของผู้ใช้:
0x00000000 - 0xbfffffff
ทุกกระบวนการของผู้ใช้ที่เพิ่งเกิดใหม่จะได้รับที่อยู่ (ช่วง) ภายในพื้นที่นี้ โดยทั่วไปกระบวนการผู้ใช้จะไม่น่าเชื่อถือดังนั้นจึงห้ามมิให้เข้าถึงพื้นที่เคอร์เนล นอกจากนี้ยังถือว่าไม่เร่งด่วนตามกฎทั่วไปเคอร์เนลพยายามเลื่อนการจัดสรรหน่วยความจำไปยังกระบวนการเหล่านั้น
ช่วงพื้นที่เคอร์เนล:
0xc0000000 - 0xffffffff
กระบวนการเคอร์เนลได้รับที่อยู่ (ช่วง) ที่นี่ เคอร์เนลสามารถเข้าถึงที่อยู่ 1 GB นี้ได้โดยตรง (ไม่ใช่เต็ม 1 GB มี 128 MB สงวนไว้สำหรับการเข้าถึงหน่วยความจำสูง)
กระบวนการที่เกิดในพื้นที่เคอร์เนลเชื่อถือได้อย่างเร่งด่วนและปราศจากข้อผิดพลาดคำขอหน่วยความจำจะได้รับการประมวลผลทันที
ทุกกระบวนการเคอร์เนลยังสามารถเข้าถึงช่วงพื้นที่ผู้ใช้หากต้องการ และเพื่อให้บรรลุสิ่งนี้เคอร์เนลแมปที่อยู่จากพื้นที่ผู้ใช้ (หน่วยความจำสูง) ไปยังพื้นที่เคอร์เนล (หน่วยความจำต่ำ), 128 MB ดังกล่าวข้างต้นถูกสงวนไว้เป็นพิเศษสำหรับเรื่องนี้
1ไม่ว่าการแบ่งจะเป็น 3/1, 2/2 หรือ 1/3 ถูกควบคุมโดยCONFIG_VMSPLIT_...
ตัวเลือก คุณสามารถตรวจสอบภายใต้/boot/config*
เพื่อดูตัวเลือกที่เลือกสำหรับเคอร์เนลของคุณ
การอ้างอิงแรกหันไปเป็นไดรเวอร์อุปกรณ์ Linux (ใช้ได้ทั้งแบบออนไลน์และในรูปแบบหนังสือ) โดยเฉพาะอย่างยิ่งบทที่ 15ซึ่งมีส่วนในหัวข้อ
ในโลกอุดมคติอุดมคติทุกองค์ประกอบของระบบจะสามารถแมปหน่วยความจำทั้งหมดที่จำเป็นต้องเข้าถึงได้ และนี่เป็นกรณีสำหรับกระบวนการบน Linux และระบบปฏิบัติการส่วนใหญ่: กระบวนการแบบ 32 บิตสามารถเข้าถึงหน่วยความจำเสมือนน้อยกว่า 2 ^ 32 ไบต์ได้เพียงเล็กน้อย (อันที่จริงแล้วประมาณ 3GB บนสถาปัตยกรรม Linux 32 บิตโดยทั่วไป) มันยากสำหรับเคอร์เนลซึ่งจะต้องสามารถแมปหน่วยความจำเต็มของกระบวนการที่ระบบเรียกว่ากำลังดำเนินการรวมทั้งหน่วยความจำกายภาพทั้งหมดรวมถึงอุปกรณ์ฮาร์ดแวร์ที่แมปหน่วยความจำอื่น ๆ
ดังนั้นเมื่อเคอร์เนลแบบ 32 บิตต้องการแมปหน่วยความจำมากกว่า 4GB ก็จะต้องมีการคอมไพล์ด้วยการรองรับหน่วยความจำสูง หน่วยความจำสูงคือหน่วยความจำที่ไม่ได้ถูกแมปอย่างถาวรในพื้นที่ที่อยู่ของเคอร์เนล (หน่วยความจำต่ำเป็นสิ่งที่ตรงกันข้าม: มันถูกแมปอยู่เสมอดังนั้นคุณจึงสามารถเข้าถึงได้ในเคอร์เนลเพียงแค่ยกเลิกการลงทะเบียนตัวชี้)
เมื่อคุณเข้าถึงหน่วยความจำสูงจากรหัสเคอร์เนลคุณต้องโทรkmap
ก่อนเพื่อรับตัวชี้จากโครงสร้างข้อมูลหน้า ( struct page
) การโทรkmap
ทำงานได้ไม่ว่าหน้าจะอยู่ในหน่วยความจำสูงหรือต่ำ นอกจากนี้ยังkmap_atomic
มีข้อ จำกัด ที่เพิ่ม แต่มีประสิทธิภาพมากขึ้นในเครื่องมัลติโปรเซสเซอร์เนื่องจากใช้การล็อคแบบละเอียดยิ่งขึ้น ตัวชี้ที่ได้รับผ่านkmap
เป็นทรัพยากร: มันใช้พื้นที่ที่อยู่ เมื่อคุณทำเสร็จแล้วคุณจะต้องโทรkunmap
(หรือkunmap_atomic
) เพื่อให้ทรัพยากรนั้นว่าง ตัวชี้จะไม่สามารถใช้งานได้อีกต่อไปและเนื้อหาของหน้านั้นไม่สามารถเข้าถึงได้จนกว่าคุณจะโทรkmap
อีกครั้ง
สิ่งนี้เกี่ยวข้องกับเคอร์เนล Linux ฉันไม่แน่ใจว่า Unix kernel จัดการกับมันอย่างไร
หน่วยความจำสูงเป็นเซ็กเมนต์ของหน่วยความจำที่โปรแกรมพื้นที่ผู้ใช้สามารถจัดการได้ มันไม่สามารถสัมผัสหน่วยความจำต่ำ
หน่วยความจำต่ำคือเซ็กเมนต์ของหน่วยความจำที่เคอร์เนล Linux สามารถจัดการได้โดยตรง หากเคอร์เนลต้องเข้าถึงหน่วยความจำสูงจะต้องทำการแมปลงในพื้นที่ที่อยู่ของตัวเองก่อน
มีการแนะนำแพตช์เมื่อเร็ว ๆ นี้ซึ่งช่วยให้คุณควบคุมตำแหน่งของกลุ่มได้ ข้อดีคือคุณสามารถนำหน่วยความจำที่กำหนดแอดเดรสออกจากพื้นที่ผู้ใช้เพื่อให้เคอร์เนลสามารถมีหน่วยความจำเพิ่มเติมที่ไม่จำเป็นต้องแมปก่อนใช้
แหล่งข้อมูลเพิ่มเติม:
HIGHMEM เป็นช่วงของพื้นที่หน่วยความจำของเคอร์เนล แต่ไม่ใช่หน่วยความจำที่คุณเข้าถึง แต่เป็นที่ที่คุณวางสิ่งที่คุณต้องการเข้าถึง
แผนที่หน่วยความจำเสมือนแบบ 32 บิต Linux โดยทั่วไปมีลักษณะดังนี้:
0x00000000-0xbfffffff: กระบวนการผู้ใช้ (3GB)
0xc0000000-0xffffffff: พื้นที่เคอร์เนล (1GB)
(เวกเตอร์เฉพาะซีพียูและสิ่งใดก็ตามจะถูกละเว้นที่นี่)
Linux แบ่งพื้นที่เคอร์เนล 1GB เป็น 2 ชิ้นคือ LOWMEM และ HIGHMEM การแยกแตกต่างกันไปตั้งแต่การติดตั้งจนถึงการติดตั้ง
หากการติดตั้งเลือกพูด 512MB-512MB สำหรับ LOW และสูง mems 512MB LOWMEM (0xc0000000-0xdfffffff) จะถูกแมปแบบคงที่ในเวลาบูตเคอร์เนล โดยปกติแล้วไบต์แรก ๆ ของหน่วยความจำฟิสิคัลจำนวนมากจะถูกใช้เพื่อการนี้เพื่อให้ที่อยู่เสมือนและฟิสิคัลในช่วงนี้มีออฟเซ็ตคงที่เช่น 0xc0000000
ในทางตรงกันข้าม 512MB หลัง (HIGHMEM) ไม่มีการแมปแบบสแตติก (แม้ว่าคุณจะสามารถแมปเพจไว้กึ่งถาวรได้ แต่คุณต้องทำอย่างชัดเจนในรหัสไดร์เวอร์ของคุณ) แต่หน้าจะถูกแมปชั่วคราวและไม่ได้แมปที่นี่เพื่อให้ที่อยู่เสมือนและที่อยู่จริงในช่วงนี้ไม่มีการแมปที่สอดคล้องกัน การใช้งานทั่วไปของ HIGHMEM รวมถึงบัฟเฟอร์ข้อมูลแบบครั้งเดียว
เท่าที่ฉันจำได้ "High Memory" ใช้สำหรับพื้นที่แอพพลิเคชันและ "Low Memory" สำหรับเคอร์เนล
ข้อดีคือแอปพลิเคชัน (พื้นที่ผู้ใช้) ไม่สามารถเข้าถึงหน่วยความจำเคอร์เนลพื้นที่
หลายคนบอกว่าหน่วยความจำเหลือน้อยสำหรับระบบปฏิบัติการ นี่เป็นเรื่องจริง แต่ไม่จำเป็นต้องเป็น หน่วยความจำสูงและหน่วยความจำต่ำเป็นเพียงสองส่วนของพื้นที่หน่วยความจำ แต่ในระบบ Linux หน่วยความจำเหลือน้อยใช้สำหรับเคอร์เนลและหน่วยความจำสูงสำหรับกระบวนการผู้ใช้เท่านั้น
ตาม "หนังสือไดโนเสาร์ (แนวคิดระบบปฏิบัติการ)" เราสามารถวางระบบปฏิบัติการในหน่วยความจำต่ำหรือหน่วยความจำสูง ปัจจัยสำคัญที่มีผลต่อการตัดสินใจครั้งนี้คือที่ตั้งของเวกเตอร์ขัดจังหวะ เนื่องจากเวกเตอร์ขัดจังหวะมักอยู่ในหน่วยความจำต่ำโปรแกรมเมอร์จึงมักจะวางระบบปฏิบัติการไว้ในหน่วยความจำต่ำเช่นกัน