ทำไมการแบ่งส่วน (ไม่)


42

ฉันกำลังศึกษาระบบปฏิบัติการและสถาปัตยกรรม x86 และในขณะที่ฉันอ่านเกี่ยวกับการแบ่งส่วนและการแบ่งหน้าฉันก็อยากรู้อยากเห็นว่าระบบปฏิบัติการที่ทันสมัยจัดการการจัดการหน่วยความจำได้อย่างไร จากสิ่งที่ฉันพบ Linux และระบบปฏิบัติการอื่น ๆ ส่วนใหญ่หลีกเลี่ยงการแบ่งส่วนเพื่อสนับสนุนการแบ่งหน้า เหตุผลสองสามข้อที่ฉันพบคือความเรียบง่ายและพกพาสะดวก

มีการใช้งานอะไรในทางปฏิบัติสำหรับการแบ่งส่วน (x86 หรืออย่างอื่น) และเราจะเคยเห็นระบบปฏิบัติการที่แข็งแกร่งใช้หรือจะใช้ระบบเพจแบบเพจต่อไป

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


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


ฉันพบเรื่องราวเล็ก ๆ น้อย ๆ ที่น่าสนใจหลังจากเชื่อมโยงกับ 'ประกาศ' ดั้งเดิมของ Linux Torvald สำหรับ Linux เขาพูดเรื่องนี้ไม่กี่โพสต์ในภายหลัง:

พูดง่ายๆว่าการย้ายพอร์ตนั้นเป็นไปไม่ได้ ส่วนใหญ่จะอยู่ใน C แต่คนส่วนใหญ่จะไม่เรียกสิ่งที่ฉันเขียน C. มันใช้ทุกคุณลักษณะที่เป็นไปได้ของ 386 ที่ฉันสามารถหาได้เพราะมันเป็นโครงการที่จะสอนฉันเกี่ยวกับ 386 ดังที่ได้กล่าวมาแล้วมันใช้ MMU สำหรับการเพจ (ไม่ใช่ดิสก์) และการแบ่งเซ็กเมนต์ มันคือการแบ่งส่วนที่ทำให้มันขึ้นอยู่กับ 386 จริงๆ (ทุกงานมีส่วน 64Mb สำหรับรหัส & ข้อมูล - สูงสุด 64 งานใน 4Gb ใครก็ตามที่ต้องการคุกกี้มากกว่า 64Mb / งาน - ยาก)

ฉันเดาว่าการทดลองของฉันกับ x86 ทำให้ฉันถามคำถามนี้ Linus ไม่มี StackOverflow ดังนั้นเขาจึงใช้มันเพื่อทดลองใช้


คุณอ่านหนังสืออะไร

1
ฉันกำลังอ่านหนังสือหลายเล่ม ฉันเริ่มถามตัวเองในขณะที่อ่านคู่มือการเขียนโปรแกรม Intel Systems (ชุดที่ 3) แต่ฉันอ่านเกี่ยวกับการจัดการหน่วยความจำ Linux เล็กน้อยใน "การทำความเข้าใจเคอร์เนล Linux" และแหล่งข้อมูลออนไลน์อื่น ๆ
Mr. Shickadance

โดยเฉพาะอย่างยิ่งฉันได้อ่านหัวข้อใน Local Descriptor Tables และฉันสงสัยว่าระบบปฏิบัติการเหล่านี้ใช้งานอย่างไร
Mr. Shickadance

1
OpenBSD รวมการแบ่งส่วน x86 และการเพจเพื่อรับการจำลองบิต NX (คุณลักษณะความปลอดภัยเพื่อห้ามการประมวลผลของหน้าข้อมูล) อาจเป็น PaX ที่ใช้สิ่งนี้ด้วย

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

คำตอบ:


31

ด้วยการแบ่งส่วนมันจะเป็นไปได้ที่จะนำแต่ละวัตถุที่จัดสรรแบบไดนามิก (malloc) ในส่วนของหน่วยความจำของตัวเอง ฮาร์ดแวร์จะตรวจสอบข้อ จำกัด ของเซ็กเมนต์โดยอัตโนมัติและคลาสทั้งหมดของบั๊กความปลอดภัย (บัฟเฟอร์โอเวอร์รัน) จะถูกกำจัด

นอกจากนี้เนื่องจากการออฟเซ็ตทั้งหมดเริ่มต้นที่ศูนย์รหัสที่รวบรวมทั้งหมดจะเป็นตำแหน่งที่เป็นอิสระโดยอัตโนมัติ การโทรเข้าสู่ DLL อื่นจะทำให้การโทรไกลด้วยการชดเชยคงที่ (ขึ้นอยู่กับฟังก์ชันที่เรียก) สิ่งนี้จะลดความซับซ้อนของ linkers และ loader

ด้วยวงแหวนป้องกัน 4 ตัวคุณสามารถออกแบบการควบคุมการเข้าถึงที่ละเอียดยิ่งขึ้น (ด้วยเพจที่คุณมีระดับการป้องกันเพียง 2 ระดับ: ผู้ใช้และหัวหน้างาน) และเคอร์เนลระบบปฏิบัติการที่แข็งแกร่งยิ่งขึ้น ตัวอย่างเช่นแหวน 0 เท่านั้นที่สามารถเข้าถึงฮาร์ดแวร์ได้อย่างสมบูรณ์ โดยการแยกเคอร์เนลระบบปฏิบัติการหลักและไดรเวอร์อุปกรณ์ออกเป็นริง 0 และ 1 คุณสามารถสร้าง microkernel OS ที่แข็งแกร่งและรวดเร็วขึ้นโดยที่ HW ส่วนใหญ่จะทำการตรวจสอบการเข้าถึงที่เกี่ยวข้อง (ไดรเวอร์อุปกรณ์สามารถเข้าถึงฮาร์ดแวร์ผ่านบิตแมปการเข้าถึง I / O ใน TSS)

อย่างไรก็ตาม .. x86 ค่อนข้าง จำกัด มีการลงทะเบียนกลุ่มข้อมูล "ฟรี" เพียง 4 ตัวเท่านั้น การโหลดซ้ำมีราคาค่อนข้างแพงและเป็นไปได้ที่จะเข้าถึงกลุ่ม 8192 เท่านั้นในเวลาเดียวกัน (สมมติว่าคุณต้องการเพิ่มจำนวนของวัตถุที่สามารถเข้าถึงได้สูงสุดดังนั้น GDT จึงมีเพียงตัวอธิบายระบบและตัวอธิบาย LDT เท่านั้น)

ขณะนี้การแบ่งส่วนโหมด 64 บิตอธิบายว่า "การสืบทอด" และการตรวจสอบขีด จำกัด ของฮาร์ดแวร์ทำได้เฉพาะในสถานการณ์ที่ จำกัด IMHO ความผิดพลาดครั้งใหญ่ อันที่จริงฉันไม่ตำหนิ Intel ฉันส่วนใหญ่ตำหนินักพัฒนาซึ่งส่วนใหญ่คิดว่าการแบ่งส่วนนั้น "ซับซ้อนเกินไป" และต้องการพื้นที่ที่อยู่แบบแฟลต ฉันยังโทษนักเขียนระบบปฏิบัติการที่ขาดจินตนาการในการแบ่งส่วนเพื่อใช้งานได้ดี (AFAIK, OS / 2 เป็นระบบปฏิบัติการเพียงระบบเดียวซึ่งใช้ประโยชน์จากคุณสมบัติการแบ่งกลุ่มอย่างสมบูรณ์)


1
นี่คือเหตุผลที่ฉันเปิดทิ้งไว้ มีบางอย่างที่แตกต่างกันในเรื่องนี้ ...
Mr. Shickadance

1
@zvrba: ช่างเป็นคำอธิบายที่ยอดเยี่ยม !!! ขอบคุณสำหรับสิ่งนั้น ตอนนี้ฉันมีข้อสงสัย: คุณไม่คิดหรือไม่ว่า INTEL สามารถชนะรางวัลใหญ่ได้ด้วยการทำให้กลุ่มที่ไม่ทับซ้อนกันและ 4GB สามารถรับความช่วยเหลือจากการเพจได้ ฉันหมายถึงอย่างที่ฉันเข้าใจว่า "การแบ่งเซ็กเมนต์ด้วยการเพจ" สามารถระบุพื้นที่ที่อยู่หน่วยความจำเสมือนได้สูงสุด 4GB และนั่นคือ 'ถั่วลิสง' !!! ลองนึกภาพความสามารถในการมี Code, Stack, Data เซกเมนต์มีขนาดใหญ่ถึง 4GB และไม่ทับซ้อนหรือทับซ้อนกันตามที่คุณต้องการ! และนั่นจะเป็นความสำเร็จครั้งใหญ่ในเวลานั้นโดยไม่ต้องเรียกร้องให้มีสถาปัตยกรรม 64 บิตเต็มรูปแบบในปัจจุบัน
fante

1
คำอธิบายที่ดีว่าทำไมการแบ่งส่วนจึงดี มันเป็นความอัปยศที่แย่มากที่มันหล่นลงมาจากทางข้าง นี่คือรายละเอียดเพิ่มเติมพร้อมรายละเอียดเพิ่มเติมสำหรับผู้ที่อยากรู้เพิ่มเติม
GDP2

1
ไม่น่าแปลกใจที่ฉันรัก OS / 2! ช่างเป็นการสูญเสียเทคโนโลยีที่มีคุณค่าอย่างแท้จริงเพราะความเขลาและการตลาด
ylluminate

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

25

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

ในกรณีของ 8086 นั้นมีที่อยู่ 20 บรรทัดบนชิปซึ่งหมายความว่ามันสามารถเข้าถึงหน่วยความจำขนาด 1Mb ได้ อย่างไรก็ตามสถาปัตยกรรมภายในนั้นใช้การระบุที่อยู่ 16 บิตซึ่งอาจเป็นเพราะความปรารถนาที่จะรักษาความสอดคล้องกับ 8080 ดังนั้นชุดคำสั่งจึงรวมส่วนการลงทะเบียนที่จะรวมกับดัชนี 16 บิตเพื่อให้สามารถระบุหน่วยความจำ 1Mb เต็ม . 80286 ขยายโมเดลนี้ด้วย MMU จริงเพื่อรองรับการป้องกันตามเซ็กเมนต์และการระบุหน่วยความจำเพิ่มเติม (iirc, 16Mb)

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

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

มันง่ายกว่ามากในการเขียนโปรแกรม MC68k ซึ่งมีสถาปัตยกรรมภายใน 32 บิตและพื้นที่ที่อยู่ทางกายภาพ 24 บิต


5
ตกลงนั่นเป็นเหตุผลทั้งหมด อย่างไรก็ตามการอ่านเอกสารของ Intel มีแนวโน้มที่จะคิดว่าเซ็กเมนต์สามารถใช้งานได้จริงเพื่อการป้องกันระดับฮาร์ดแวร์ที่มากขึ้นจากข้อบกพร่องของโปรแกรม ส่วนเฉพาะ 3.2.3 ของคำแนะนำการเขียนโปรแกรมระบบ - มีประโยชน์กับรุ่นหลายส่วนหรือไม่? มันจะถูกต้องหรือไม่ที่จะบอกว่าลีนุกซ์ใช้โมเดลป้องกันแบบแบน (ส่วน 3.2.2)
Mr. Shickadance

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

1
ขอขอบคุณคุณได้นำความทรงจำที่อดกลั้นกลับมาใช้ในการประมวลผลภาพในหน่วยความจำแบบแบ่งกลุ่ม - นี่จะหมายถึงการบำบัดที่มากขึ้น!
Martin Beckett

10
คุณเข้าใจผิดการแบ่งส่วนอย่างสมบูรณ์ ใน 8086 อาจเป็นแฮ็ค 80286 เปิดตัวโหมดป้องกันที่สำคัญสำหรับการป้องกัน ใน 80386 มันขยายเพิ่มเติมและเซ็กเมนต์สามารถมากกว่า 64kB ยังคงมีประโยชน์ของการตรวจสอบฮาร์ดแวร์ (BTW, 80286 ไม่มี MMU)
zvrba

2
ย้อนกลับไปในปี 1985 เมื่อมีการเปิดตัว 386 พื้นที่ที่อยู่ 4 GiB ได้รับการพิจารณาว่ามีขนาดใหญ่มาก โปรดจำไว้ว่าฮาร์ดดิสก์ขนาด 20 MiB นั้นค่อนข้างใหญ่ในเวลานั้นและมันก็ไม่ใช่เรื่องแปลกที่ระบบจะมาพร้อมกับฟล็อปปี้ดิสก์เท่านั้น 3.5 "FDD ถูกนำมาใช้ในปี 1983 โดยมีความจุในรูปแบบที่ 360 KB (1.44 MB 3.5" FDD มีให้บริการในปี 1986) ภายในข้อผิดพลาดจากการทดลอง 64 บิต: เข้าถึงร่างกาย แต่มีขนาดใหญ่เพื่อให้เป็นไปในทางปฏิบัติไม่มีที่สิ้นสุด
CVn

15

สำหรับ 80x86 มี 4 ตัวเลือกคือ "ไม่มีอะไร" การแบ่งเซ็กเมนต์เท่านั้นการแบ่งหน้าเท่านั้นและทั้งการแบ่งส่วนและการแบ่งหน้า

สำหรับ "ไม่มีอะไร" (ไม่มีการแบ่งส่วนหรือการแบ่งหน้า) คุณจะไม่มีวิธีที่ง่ายในการปกป้องกระบวนการจากตัวเองไม่มีวิธีที่ง่ายในการปกป้องกระบวนการจากกันและกันไม่มีวิธีจัดการกับสิ่งต่าง ๆ เช่นการกระจายตัวของพื้นที่ที่อยู่ทางกายภาพ รหัสอิสระ ฯลฯ แม้จะมีปัญหาเหล่านี้แล้วก็ตาม (ในทางทฤษฎี) อาจมีประโยชน์ในบางสถานการณ์ (เช่นอุปกรณ์ฝังตัวที่รันเพียงแอปพลิเคชั่นเดียวหรืออาจเป็นสิ่งที่ใช้ JIT และจำลองทุกอย่างต่อไป)

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

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

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

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

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

ในที่สุด AMD ออกแบบโหมดยาว ไม่มีรหัส 64 บิตเก่า / ที่มีอยู่ที่ต้องกังวลดังนั้น (สำหรับรหัส 64 บิต) เอเอ็มดีกำจัดการแบ่งส่วนมากที่สุดเท่าที่จะทำได้ สิ่งนี้ทำให้นักพัฒนาระบบปฏิบัติการยังมีอีกเหตุผลหนึ่ง (ไม่มีวิธีที่ง่ายในการโค้ดพอร์ตที่ออกแบบมาสำหรับการแบ่งเซ็กเมนต์เป็น 64- บิต) เพื่อหลีกเลี่ยงการแบ่งส่วนต่อไป


13

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

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

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

Intel ยังพยายามสร้าง super-micro ที่มีความสามารถมากกว่าเดิมซึ่งเรียกว่าiAPX 432ซึ่งจะสามารถเอาชนะสิ่งอื่นได้ในเวลานั้นและมีสถาปัตยกรรมหน่วยความจำแบบแบ่งส่วนและคุณสมบัติอื่น ๆ ที่มุ่งเน้นการเขียนโปรแกรมเชิงวัตถุ การติดตั้งดั้งเดิมนั้นช้าเกินไปและไม่มีการพยายามแก้ไขเพิ่มเติม

การอภิปรายอย่างละเอียดยิ่งขึ้นเกี่ยวกับวิธีการใช้การแบ่งส่วนและการเพจใน Multics สามารถพบได้ในกระดาษของ Paul Green หน่วยความจำเสมือนจริง Multics - บทช่วยสอนและการสะท้อน


1
ข้อมูลที่ยอดเยี่ยมและข้อโต้แย้งที่ยอดเยี่ยม Thanx สำหรับลิงค์พวกมันล้ำค่า !!!
fante

1
ขอบคุณสำหรับการเชื่อมโยงกับ Multics และสำหรับคำตอบที่ให้ข้อมูลอย่างมาก! การแบ่งส่วนอย่างชัดเจนเหนือกว่าในหลาย ๆ สิ่งที่เราทำในขณะนี้
GDP2

1
คำตอบของคุณคืออัญมณีที่แท้จริงในความหยาบ ขอบคุณมากสำหรับการแบ่งปันข้อมูลเชิงลึกที่เราได้สูญเสียไป มันทำให้ฉันปรารถนาที่จะเห็นผลตอบแทนจากการแบ่งเซ็กเมนต์ผ่านการพัฒนาระบบปฏิบัติการที่เหมาะสมซึ่งสามารถกระตุ้นการปรับแต่งฮาร์ดแวร์ ปัญหามากมายจริงๆสามารถแก้ไขได้ด้วยวิธีนี้! แม้ฟังดูเหมือนว่าเราจะได้รับภาษา OOP จริงที่ระดับประสิทธิภาพที่สูงขึ้นมากและโลหะเปลือยที่มีการแบ่งส่วน
ylluminate

6

การแบ่งส่วนเป็นแฮ็ค / วิธีแก้ปัญหาเพื่ออนุญาตให้หน่วยความจำสูงสุด 1MB ได้รับการแก้ไขโดยตัวประมวลผล 16 บิตโดยปกติหน่วยความจำ 64K เท่านั้นที่จะสามารถเข้าถึงได้

เมื่อโปรเซสเซอร์ 32 บิตมาพร้อมกันคุณสามารถจัดการหน่วยความจำได้สูงสุด 4GB พร้อมกับโมเดลหน่วยความจำแบบแบนและไม่ต้องการการแบ่งกลุ่มอีกต่อไป - การลงทะเบียนเซกเมนต์ได้ถูกนำมาใช้ใหม่เป็นตัวเลือกสำหรับ GDT / เพจจิ้งในโหมดป้องกัน มีโหมดการป้องกัน 16 บิต)

นอกจากนี้โหมดหน่วยความจำแบบแบนยังสะดวกกว่าสำหรับคอมไพเลอร์ด้วย - คุณสามารถเขียนโปรแกรมที่แบ่งเป็น 16 บิตใน Cแต่ก็ยุ่งยากหน่อย หน่วยความจำแบบแบนทำให้ทุกอย่างง่ายขึ้น


มีการพูดถึง 'การป้องกัน' จากการแบ่งกลุ่มเมื่อเราสามารถใช้การเพจแทนได้หรือไม่?
Mr. Shickadance

1
@นาย. การแบ่งส่วน Shickadance ไม่มีการป้องกันหน่วยความจำใด ๆ - สำหรับการป้องกันหน่วยความจำคุณต้องมีโหมดการป้องกันที่คุณสามารถป้องกันหน่วยความจำโดยใช้ GDT หรือการเพจ
Justin

5

สถาปัตยกรรมบางอย่าง (เช่น ARM) ไม่สนับสนุนเซ็กเมนต์หน่วยความจำเลย ถ้าลีนุกซ์นั้นขึ้นอยู่กับแหล่งที่มามันจะไม่สามารถส่งไปยังสถาปัตยกรรมเหล่านั้นได้อย่างง่ายดาย

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

มีเวลาประมาณช่วงเปลี่ยนของยุค 80 เมื่อ Intel ในฐานะองค์กรกำลังคาดการณ์ถึงความนิยมในอนาคตของ Ada และภาษาการเขียนโปรแกรมระดับสูงอื่น ๆ ในอนาคต นี่เป็นพื้นฐานที่ความล้มเหลวที่น่าทึ่งของพวกเขาบางอย่างเช่นการแบ่งเซ็กเมนต์หน่วยความจำ APX432 และ 286 ที่น่ากลัวมาจาก ด้วย 386 พวกเขายอมจำนนต่อโปรแกรมเมอร์หน่วยความจำแบบแบน เพจจิ้งและ TLB ถูกเพิ่มและส่วนที่ถูกทำให้ปรับขนาดได้ถึง 4GB จากนั้น AMD ก็ลบเซ็กเมนต์ด้วย x86_64 โดยการทำให้ reg reg เป็นแบบ dont-care / impl-0 (ยกเว้น fs? สำหรับ TLS ฉันคิดว่า?)

ต้องบอกว่าข้อดีของเซ็กเมนต์หน่วยความจำชัดเจน - การสลับพื้นที่ที่อยู่โดยไม่ต้อง repopulate TLB บางทีสักวันใครบางคนจะสร้างซีพียูที่มีประสิทธิภาพในการแข่งขันที่รองรับการแบ่งเซ็กเมนต์เราสามารถตั้งโปรแกรมระบบปฏิบัติการที่เน้นเซ็กเมนต์สำหรับมันและโปรแกรมเมอร์สามารถทำให้ Ada / Pascal / D / Rust / อีกค่า - ไม่ได้ต้องการแบน โปรแกรมหน่วยความจำสำหรับมัน


1

การแบ่งกลุ่มเป็นภาระอย่างมากสำหรับนักพัฒนาแอปพลิเคชัน นี่คือที่มาของการแบ่งส่วนใหญ่ออกไป

ที่น่าสนใจฉันมักจะสงสัยว่า i86 จะดีกว่านี้ได้มากแค่ไหนถ้า Intel ลบล้างการสนับสนุนแบบดั้งเดิมสำหรับโหมดเก่าเหล่านี้ ที่นี่ดีกว่าจะบ่งบอกถึงพลังงานที่ลดลงและอาจดำเนินการได้เร็วขึ้น

ฉันเดาว่าคงเถียงได้ว่า Intel ทำให้นมเปรี้ยวด้วยเซ็กเมนต์ 16 บิตที่นำไปสู่การปฏิวัติหลายประเภท แต่ลองมาดูกันพื้นที่แอดเดรส 64k นั้นไม่มีอะไรพิเศษโดยเฉพาะเมื่อคุณดูแอพที่ทันสมัย ในที่สุดพวกเขาต้องทำอะไรบางอย่างเพราะการแข่งขันทำได้และทำตลาดได้อย่างมีประสิทธิภาพกับปัญหาพื้นที่ที่อยู่ของ i86


1

การแบ่งส่วนทำให้การแปลและการสลับหน้าช้าลง

ด้วยเหตุผลเหล่านี้การแบ่งส่วนได้ลดลงอย่างมากใน x86-64

ความแตกต่างที่สำคัญระหว่างพวกเขาคือ:

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

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

|   | process 1 |       | process 2 |                        |
     -----------         -----------
0                                                            max

ในที่สุดจะกลายเป็นกระบวนการ 1 ที่เติบโตขึ้น:

|   | process 1        || process 2 |                        |
     ------------------  -------------
0                                                            max

จนกว่าการแยกจะหลีกเลี่ยงไม่ได้:

|   | process 1 part 1 || process 2 |   | process 1 part 2 | |
     ------------------  -----------     ------------------
0                                                            max

ณ จุดนี้:

  • วิธีเดียวในการแปลหน้าคือทำการค้นหาแบบไบนารีบนทุกหน้าของกระบวนการ 1 ซึ่งใช้บันทึกที่ไม่สามารถยอมรับได้ (n)
  • การสลับจากกระบวนการ 1 ส่วนที่ 1 อาจมีขนาดใหญ่เนื่องจากส่วนนั้นอาจมีขนาดใหญ่

ด้วยขนาดหน้าคงที่:

  • การแปลแบบ 32 บิตทุกครั้งจะมีเพียง 2 หน่วยความจำเท่านั้นที่อ่านได้: ไดเรกทอรีและหน้าตารางการเดิน
  • การสลับทุกครั้งเป็น 4KiB ที่ยอมรับได้

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

ดูเพิ่มเติมที่: https://stackoverflow.com/questions/18431261/how-does-x86-paging-work

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