ความแตกต่างระหว่างพื้นที่เคอร์เนลและพื้นที่ผู้ใช้คืออะไร? เคอร์เนลพื้นที่เคอร์เนลเธรดกระบวนการเคอร์เนลและเคอร์เนลสแต็คหมายถึงสิ่งเดียวกันหรือไม่ นอกจากนี้ทำไมเราจึงต้องการความแตกต่างนี้
ความแตกต่างระหว่างพื้นที่เคอร์เนลและพื้นที่ผู้ใช้คืออะไร? เคอร์เนลพื้นที่เคอร์เนลเธรดกระบวนการเคอร์เนลและเคอร์เนลสแต็คหมายถึงสิ่งเดียวกันหรือไม่ นอกจากนี้ทำไมเราจึงต้องการความแตกต่างนี้
คำตอบ:
จริงๆคำตอบที่ง่ายก็คือว่าเคอร์เนลทำงานในพื้นที่เคอร์เนลและโปรแกรมปกติทำงานในพื้นที่ของผู้ใช้ พื้นที่ของผู้ใช้นั้นเป็นรูปแบบของ sand-boxing - มัน จำกัด โปรแกรมผู้ใช้ดังนั้นพวกเขาจึงไม่สามารถยุ่งกับหน่วยความจำ (และทรัพยากรอื่น ๆ ) ที่เป็นเจ้าของโดยโปรแกรมอื่น ๆ หรือโดยเคอร์เนลระบบปฏิบัติการ ขีด จำกัด นี้ (แต่โดยปกติจะไม่กำจัดทั้งหมด) ความสามารถในการทำสิ่งที่ไม่ดีเช่นการกระแทกเครื่อง
เคอร์เนลเป็นแกนหลักของระบบปฏิบัติการ โดยปกติจะสามารถเข้าถึงหน่วยความจำและฮาร์ดแวร์ของเครื่องทั้งหมดได้ (และทุกอย่างในเครื่อง) เพื่อให้เครื่องมีความเสถียรที่สุดเท่าที่จะเป็นไปได้โดยปกติแล้วคุณต้องการเพียงรหัสที่น่าเชื่อถือและผ่านการทดสอบเป็นอย่างดีเพื่อให้ทำงานในโหมดเคอร์เนล / พื้นที่เคอร์เนล
สแต็คเป็นเพียงส่วนหนึ่งของหน่วยความจำดังนั้นโดยปกติแล้วมันจะถูกแยกออกไปพร้อมกับหน่วยความจำส่วนที่เหลือ
Random Access Memory (RAM) สามารถแบ่งเหตุผลออกเป็นสองภูมิภาคที่แตกต่างกันคือ -. พื้นที่เคอร์เนลและพื้นที่การใช้ ( ที่อยู่ทางกายภาพของ RAM ยังไม่ได้แบ่งออกจริงเท่านั้นที่อยู่เสมือนทั้งหมดนี้ดำเนินการโดยMMU )
เคอร์เนลทำงานในส่วนของหน่วยความจำที่มีสิทธิ์ หน่วยความจำส่วนนี้ไม่สามารถเข้าถึงได้โดยตรงโดยกระบวนการของผู้ใช้ปกติในขณะที่เคอร์เนลสามารถเข้าถึงทุกส่วนของหน่วยความจำ ในการเข้าถึงเป็นส่วนหนึ่งของเคอร์เนลบางกระบวนการผู้ใช้ต้องใช้ระบบที่กำหนดไว้ล่วงหน้าโทรเช่นopen
, read
, write
ฯลฯ นอกจากนี้C
ฟังก์ชั่นห้องสมุดเช่นprintf
การโทรสายระบบwrite
ในการเปิด
การเรียกระบบทำหน้าที่เป็นส่วนต่อประสานระหว่างกระบวนการผู้ใช้กับกระบวนการเคอร์เนล สิทธิ์การเข้าถึงถูกวางไว้บนพื้นที่เคอร์เนลเพื่อหยุดผู้ใช้ไม่ให้ยุ่งกับเคอร์เนลโดยไม่รู้ตัว
ดังนั้นเมื่อมีการเรียกระบบเกิดการขัดจังหวะของซอฟต์แวร์จะถูกส่งไปยังเคอร์เนล CPU อาจมอบการควบคุมเป็นการชั่วคราวไปยังรูทีนตัวจัดการขัดจังหวะที่เกี่ยวข้อง กระบวนการเคอร์เนลซึ่งหยุดโดยการขัดจังหวะการดำเนินการต่อหลังจากที่รูทีนตัวจัดการขัดจังหวะเสร็จงาน
พื้นที่เคอร์เนลและพื้นที่เสมือนเป็นแนวคิดของหน่วยความจำเสมือน .... ไม่ได้หมายความว่า Ram (หน่วยความจำจริงของคุณ) แบ่งออกเป็นพื้นที่เคอร์เนลและผู้ใช้ แต่ละกระบวนการจะได้รับหน่วยความจำเสมือนซึ่งแบ่งออกเป็นพื้นที่เคอร์เนลและผู้ใช้
ดังนั้นการพูดว่า "หน่วยความจำเข้าถึงโดยสุ่ม (RAM) สามารถแบ่งออกเป็นสองส่วนคือ - พื้นที่เคอร์เนลและพื้นที่ผู้ใช้" มันผิด.
& เกี่ยวกับสิ่งที่ "เคอร์เนลพื้นที่เทียบกับพื้นที่ผู้ใช้"
เมื่อกระบวนการถูกสร้างขึ้นและหน่วยความจำเสมือนของมันถูกแบ่งออกเป็นพื้นที่ผู้ใช้และเคอร์เนลพื้นที่ซึ่งพื้นที่พื้นที่ผู้ใช้มีข้อมูลรหัสกองซ้อนกองของกระบวนการ & เคอร์เนลพื้นที่มีสิ่งต่าง ๆ เช่นตารางหน้าสำหรับกระบวนการ โครงสร้างข้อมูลเคอร์เนลและรหัสเคอร์เนล ฯลฯ หากต้องการเรียกใช้รหัสพื้นที่เคอร์เนลการควบคุมจะต้องเปลี่ยนไปใช้โหมดเคอร์เนล (โดยใช้ซอฟต์แวร์ขัดจังหวะ 0x80 สำหรับการโทรของระบบ) & เคอร์เนลสแต็กจะใช้ร่วมกันโดยทั่วไประหว่างกระบวนการทั้งหมดที่ดำเนินการในพื้นที่เคอร์เนล
วงแหวน CPU เป็นความแตกต่างที่ชัดเจนที่สุด
ในโหมดที่ได้รับการป้องกัน x86 ซีพียูจะอยู่ในหนึ่งใน 4 วงเสมอ เคอร์เนล Linux ใช้ 0 และ 3 เท่านั้น:
นี่เป็นนิยามที่ยากและรวดเร็วที่สุดของ kernel vs userland
ทำไม Linux ไม่ใช้ริง 1 และ 2: CPU Privilege Rings: ทำไมไม่ใช้ริง 1 และ 2
วงแหวนปัจจุบันถูกกำหนดอย่างไร?
แหวนปัจจุบันถูกเลือกโดยการรวมกันของ:
ตารางตัวอธิบายทั่วโลก: ตารางในหน่วยความจำของรายการ GDT และแต่ละรายการมีเขตข้อมูลPrivl
ที่เข้ารหัสแหวน
คำสั่ง LGDT ตั้งค่าที่อยู่เป็นตารางตัวอธิบายปัจจุบัน
ดูเพิ่มเติมที่: http://wiki.osdev.org/Global_Descriptor_Table
ส่วนที่ลงทะเบียน CS, DS ฯลฯ ซึ่งชี้ไปที่ดัชนีของรายการใน GDT
ตัวอย่างเช่นCS = 0
หมายถึงรายการแรกของ GDT ใช้งานได้ในปัจจุบันสำหรับรหัสดำเนินการ
แหวนแต่ละวงทำอะไรได้บ้าง?
ชิปซีพียูถูกสร้างขึ้นทางกายภาพเพื่อที่:
แหวน 0 สามารถทำอะไรก็ได้
แหวน 3 ไม่สามารถเรียกใช้หลายคำสั่งและเขียนไปยังหลาย ๆ รีจิสเตอร์ได้อย่างยอดเยี่ยมที่สุด:
ไม่สามารถเปลี่ยนแหวนของตัวเองได้! มิฉะนั้นมันอาจตั้งค่าตัวเองให้แหวน 0 และแหวนจะไร้ประโยชน์
กล่าวอีกนัยหนึ่งไม่สามารถแก้ไขตัวอธิบายส่วนปัจจุบันซึ่งกำหนดแหวนปัจจุบัน
ไม่สามารถปรับเปลี่ยนตารางหน้า: การเพจ x86 ทำงานอย่างไร
กล่าวอีกนัยหนึ่งไม่สามารถแก้ไขการลงทะเบียน CR3 และเพจตัวเองป้องกันการแก้ไขตารางหน้า
สิ่งนี้ป้องกันไม่ให้กระบวนการหนึ่งเห็นหน่วยความจำของกระบวนการอื่นเพื่อความปลอดภัย / ความง่ายในการเขียนโปรแกรมด้วยเหตุผล
ไม่สามารถลงทะเบียนตัวจัดการขัดจังหวะ สิ่งเหล่านั้นถูกกำหนดค่าโดยการเขียนไปยังตำแหน่งหน่วยความจำซึ่งถูกป้องกันโดยการเพจ
ตัวจัดการทำงานในวงแหวน 0 และจะทำลายโมเดลความปลอดภัย
กล่าวอีกนัยหนึ่งไม่สามารถใช้คำแนะนำ LGDT และ LIDT
ไม่สามารถทำคำแนะนำ IO เหมือนin
และout
และทำให้มีการเข้าถึงฮาร์ดแวร์โดยพลการ
มิฉะนั้นยกตัวอย่างเช่นการอนุญาตของไฟล์จะไร้ประโยชน์หากโปรแกรมใด ๆ สามารถอ่านจากดิสก์โดยตรง
แม่นยำมากขึ้นต้องขอบคุณไมเคิลเพชร : มันเป็นไปได้จริงสำหรับ OS เพื่อให้คำแนะนำ IO แหวน 3 นี้จะถูกควบคุมจริงโดยส่วนงานรัฐ
สิ่งที่เป็นไปไม่ได้คือแหวน 3 จะให้สิทธิ์ตัวเองในการทำเช่นนั้นหากไม่มีในตอนแรก
ลินุกซ์ไม่อนุญาตมันเสมอ ดูเพิ่มเติมที่: ทำไม Linux ไม่ใช้การสลับบริบทฮาร์ดแวร์ผ่าน TSS
โปรแกรมและระบบปฏิบัติการมีการเปลี่ยนแปลงระหว่างวงแหวนอย่างไร
เมื่อซีพียูเปิดทำงานมันจะเริ่มต้นรันโปรแกรมเริ่มต้นในริง 0 (แบบดี แต่มันเป็นการประมาณที่ดี) คุณสามารถคิดว่าโปรแกรมเริ่มต้นนี้เป็นเคอร์เนล (แต่โดยปกติจะเป็น bootloader ที่เรียกเคอร์เนลยังคงอยู่ในแหวน 0 )
เมื่อกระบวนการของผู้ใช้ต้องการให้เคอร์เนลทำอะไรบางอย่างเพื่อให้มันเหมือนกับเขียนไฟล์มันใช้คำสั่งที่สร้างการขัดจังหวะเช่นint 0x80
หรือsyscall
ส่งสัญญาณเคอร์เนล x86-64 Linux syscall ตัวอย่าง Hello world:
.data
hello_world:
.ascii "hello world\n"
hello_world_len = . - hello_world
.text
.global _start
_start:
/* write */
mov $1, %rax
mov $1, %rdi
mov $hello_world, %rsi
mov $hello_world_len, %rdx
syscall
/* exit */
mov $60, %rax
mov $0, %rdi
syscall
รวบรวมและเรียกใช้:
as -o hello_world.o hello_world.S
ld -o hello_world.out hello_world.o
./hello_world.out
GitHub ต้นน้ำ
เมื่อสิ่งนี้เกิดขึ้น CPU จะเรียกตัวจัดการการติดต่อกลับขัดจังหวะซึ่งเคอร์เนลที่ลงทะเบียนในเวลาบูต นี่คือตัวอย่างที่เป็นรูปธรรมที่ BareMetal ลงทะเบียนจัดการและการใช้งานมัน
ตัวจัดการนี้ทำงานในวงแหวน 0 ซึ่งตัดสินใจว่าเคอร์เนลจะอนุญาตการดำเนินการนี้ดำเนินการและรีสตาร์ทโปรแกรม userland ในวงแหวน 3 x86_64
เมื่อมีการexec
ใช้การเรียกระบบ (หรือเมื่อเคอร์เนลจะเริ่มทำงาน/init
) เคอร์เนลจะจัดเตรียมการลงทะเบียนและหน่วยความจำของกระบวนการ userland ใหม่จากนั้นจะข้ามไปยังจุดเริ่มต้นและสลับ CPU ไปยังวงแหวน 3
หากโปรแกรมพยายามทำสิ่งที่ซุกซนเช่นเขียนไปยังการลงทะเบียนต้องห้ามหรือที่อยู่หน่วยความจำ (เพราะเพจจิ้ง) ซีพียูยังเรียกตัวจัดการการเรียกกลับเคอร์เนลในแหวน 0
แต่เนื่องจาก userland ซนเคอร์เนลอาจฆ่ากระบวนการในเวลานี้หรือแจ้งเตือนด้วยสัญญาณ
เมื่อเคอร์เนลบูทจะทำการติดตั้งนาฬิกาฮาร์ดแวร์ด้วยความถี่คงที่ซึ่งสร้างอินเทอร์รัปต์เป็นระยะ
นาฬิกาฮาร์ดแวร์นี้สร้างการขัดจังหวะที่เรียกใช้วงแหวน 0 และอนุญาตให้กำหนดเวลาว่ากระบวนการ userland ใดที่จะปลุก
ด้วยวิธีนี้การกำหนดเวลาสามารถเกิดขึ้นได้แม้ว่ากระบวนการจะไม่ทำการเรียกระบบใด ๆ
อะไรคือจุดที่มีหลายวง
มีข้อดีสองประการที่สำคัญของการแยกเคอร์เนลและ userland:
จะเล่นกับมันอย่างไร?
ฉันได้สร้างการตั้งค่าโลหะเปลือยที่ควรจะเป็นวิธีที่ดีในการจัดการกับแหวนโดยตรง: https://github.com/cirosantilli/x86-bare-metal-examples
ฉันไม่ได้มีความอดทนในการสร้างตัวอย่าง userland อย่างน่าเสียดาย แต่ฉันไปไกลถึงการตั้งค่าการเพจดังนั้น userland ควรเป็นไปได้ ฉันชอบที่จะเห็นคำขอดึง
อีกวิธีหนึ่งคือโมดูลเคอร์เนล Linux ทำงานในริง 0 ดังนั้นคุณสามารถใช้มันเพื่อลองการดำเนินการพิเศษเช่นอ่านการลงทะเบียนควบคุม: วิธีการเข้าถึงตัวควบคุมรีจิสเตอร์ cr0, cr2, cr3 จากโปรแกรม? รับข้อผิดพลาดการแบ่งกลุ่ม
นี่คือการตั้งค่า QEMU + Buildroot ที่สะดวกเพื่อทดลองใช้งานโดยไม่ต้องฆ่าโฮสต์ของคุณ
ข้อเสียของโมดูลเคอร์เนลคือ kthreads อื่นกำลังทำงานและอาจรบกวนการทดลองของคุณ แต่ในทางทฤษฎีคุณสามารถจัดการตัวขัดจังหวะทั้งหมดด้วยโมดูลเคอร์เนลของคุณและเป็นเจ้าของระบบซึ่งจะเป็นโครงการที่น่าสนใจ
แหวนเชิงลบ
ในขณะที่วงแหวนด้านลบนั้นไม่ได้อ้างอิงในคู่มือ Intel จริง ๆ แล้วมีโหมด CPU ที่มีความสามารถเพิ่มเติมนอกเหนือจากวงแหวน 0 นั้นจึงเหมาะสำหรับชื่อ "แหวนลบ"
ตัวอย่างหนึ่งคือโหมดไฮเปอร์ไวเซอร์ที่ใช้ในการจำลองเสมือน
สำหรับรายละเอียดเพิ่มเติมดู:
แขน
ใน ARM แหวนจะเรียกว่า Exception Levels แทน แต่ความคิดหลักยังคงเหมือนเดิม
มีข้อยกเว้น 4 ระดับใน ARMv8 ซึ่งมักใช้เป็น:
EL0: userland
EL1: เคอร์เนล ("ผู้ควบคุม" ในคำศัพท์ ARM)
ป้อนด้วยsvc
คำสั่ง (SuperVisor Call) ซึ่งก่อนหน้านี้รู้จักกันก่อนหน้านี้ว่าเป็นswi
แอสเซมบลีรวมซึ่งเป็นคำสั่งที่ใช้ในการโทรระบบ Linux สวัสดีชาวโลกตัวอย่าง ARMv8:
hello.S
.text
.global _start
_start:
/* write */
mov x0, 1
ldr x1, =msg
ldr x2, =len
mov x8, 64
svc 0
/* exit */
mov x0, 0
mov x8, 93
svc 0
msg:
.ascii "hello syscall v8\n"
len = . - msg
GitHub ต้นน้ำ
ทดสอบกับ QEMU บน Ubuntu 16.04:
sudo apt-get install qemu-user gcc-arm-linux-gnueabihf
arm-linux-gnueabihf-as -o hello.o hello.S
arm-linux-gnueabihf-ld -o hello hello.o
qemu-arm hello
นี่เป็นตัวอย่างที่เป็นรูปธรรมที่ BareMetal ลงทะเบียนการจัดการ SVC และไม่รับสายเรียก
EL2: hypervisorsเช่นXen
เข้ามาพร้อมกับhvc
คำแนะนำ (HyperVisor Call)
ไฮเปอร์ไวเซอร์คือระบบปฏิบัติการระบบปฏิบัติการคืออะไรสำหรับผู้ใช้
ตัวอย่างเช่น Xen อนุญาตให้คุณเรียกใช้หลาย OS เช่น Linux หรือ Windows บนระบบเดียวกันในเวลาเดียวกันและมันแยก OS ต่างๆออกจากกันเพื่อความปลอดภัยและความสะดวกในการดีบักเช่นเดียวกับ Linux สำหรับโปรแกรมผู้ใช้
Hypervisors เป็นส่วนสำคัญของโครงสร้างพื้นฐานคลาวด์ในปัจจุบัน: อนุญาตให้เซิร์ฟเวอร์หลาย ๆ ตัวทำงานบนฮาร์ดแวร์เดียวทำให้การใช้งานฮาร์ดแวร์ใกล้เคียง 100% และประหยัดเงินได้มาก
AWS เช่นใช้ Xen จนกระทั่ง 2017 เมื่อย้ายไป KVM ทำข่าว
EL3: อีกระดับหนึ่ง ตัวอย่างสิ่งที่ต้องทำ
เข้าสู่smc
คำสั่ง (การเรียกใช้โหมดปลอดภัย)
ARMv8 สถาปัตยกรรมแบบอ้างอิง DDI 0487C.a - บท D1 - ระดับ AArch64 ระบบโปรแกรมเมอร์รุ่น - รูปที่แสดงให้เห็นถึง D1-1 นี้สวยงาม:
สถานการณ์การเปลี่ยนแปลง ARM bit กับการถือกำเนิดของARMv8.1 Virtualization ส่วนขยายโฮสต์ (VHE) ส่วนขยายนี้ช่วยให้เคอร์เนลทำงานใน EL2 ได้อย่างมีประสิทธิภาพ:
VHE ถูกสร้างขึ้นเนื่องจากโซลูชันการจำลองเสมือนในเคอร์เนลใน Linux เช่น KVM ได้รับการพัฒนาบน Xen (ดูตัวอย่างเช่นการย้าย AWS ไปยัง KVM ที่กล่าวถึงข้างต้น) เนื่องจากไคลเอนต์ส่วนใหญ่ต้องการ Linux VM เท่านั้นและอย่างที่คุณสามารถจินตนาการได้ โครงการ KVM นั้นง่ายกว่าและมีประสิทธิภาพมากกว่า Xen ดังนั้นตอนนี้เคอร์เนลโฮสต์ Linux ทำหน้าที่เป็นไฮเปอร์ไวเซอร์ในกรณีเหล่านั้น
สังเกตว่า ARM อาจจะเป็นเพราะประโยชน์ของการเข้าใจถึงปัญหาหลังเหตุการณ์มีการตั้งชื่อที่ดีกว่าสำหรับระดับสิทธิ์มากกว่า x86 โดยไม่จำเป็นต้องมีระดับลบ: 0 เป็นต่ำและ 3 สูงที่สุด ระดับที่สูงขึ้นมีแนวโน้มที่จะถูกสร้างขึ้นบ่อยกว่าระดับที่ต่ำกว่า
EL ปัจจุบันสามารถสอบถามด้วยMRS
คำสั่ง: อะไรคือโหมดการดำเนินการปัจจุบัน / ระดับข้อยกเว้น ฯลฯ ?
ARM ไม่จำเป็นต้องมีระดับการยกเว้นทั้งหมดเพื่อให้มีการใช้งานที่ไม่ต้องการคุณสมบัติในการบันทึกพื้นที่ชิป ARMv8 "ระดับการยกเว้น" พูดว่า:
การใช้งานอาจไม่รวมถึงระดับข้อยกเว้นทั้งหมด การใช้งานทั้งหมดจะต้องมี EL0 และ EL1 EL2 และ EL3 เป็นตัวเลือก
QEMU เช่นค่าเริ่มต้นเป็น EL1 แต่สามารถเปิดใช้งาน EL2 และ EL3 พร้อมตัวเลือกบรรทัดคำสั่ง: qemu-system-aarch64 ป้อน el1 เมื่อทำการจำลองกำลังไฟ a53
ตัวอย่างโค้ดทดสอบบน Ubuntu 18.10
พื้นที่เคอร์เนลและพื้นที่ผู้ใช้เป็นการแยกฟังก์ชั่นระบบปฏิบัติการที่มีสิทธิพิเศษและแอ็พพลิเคชันผู้ใช้ที่ถูก จำกัด การแยกมีความจำเป็นเพื่อป้องกันแอปพลิเคชันผู้ใช้จากการปล้นคอมพิวเตอร์ของคุณ มันจะเป็นสิ่งที่ไม่ดีถ้าโปรแกรมผู้ใช้เก่าสามารถเริ่มเขียนข้อมูลแบบสุ่มไปยังฮาร์ดไดรฟ์ของคุณหรืออ่านหน่วยความจำจากพื้นที่หน่วยความจำของโปรแกรมผู้ใช้อื่น
โปรแกรมพื้นที่ผู้ใช้ไม่สามารถเข้าถึงทรัพยากรของระบบได้โดยตรงดังนั้นการเข้าถึงถูกจัดการในนามของโปรแกรมโดยเคอร์เนลระบบปฏิบัติการ โดยทั่วไปโปรแกรมพื้นที่ผู้ใช้ทำการร้องขอดังกล่าวของระบบปฏิบัติการผ่านการเรียกระบบ
เคอร์เนลเธรดกระบวนการสแต็กไม่ได้หมายถึงสิ่งเดียวกัน พวกเขาเป็นโครงสร้างคล้ายกันสำหรับพื้นที่เคอร์เนลเป็นคู่ของพวกเขาในพื้นที่ผู้ใช้
แต่ละกระบวนการมีหน่วยความจำเสมือน 4GB ของตัวเองซึ่งจับคู่กับหน่วยความจำกายภาพผ่านตารางหน้า หน่วยความจำเสมือนส่วนใหญ่จะแบ่งออกเป็นสองส่วน: 3 GB สำหรับการใช้กระบวนการและ 1 GB สำหรับการใช้เคอร์เนล ตัวแปรส่วนใหญ่ที่คุณสร้างจะอยู่ในส่วนแรกของพื้นที่ที่อยู่ ส่วนนั้นเรียกว่าพื้นที่ผู้ใช้ ส่วนสุดท้ายคือตำแหน่งที่เคอร์เนลอยู่และเป็นเรื่องปกติสำหรับกระบวนการทั้งหมด สิ่งนี้เรียกว่าพื้นที่เคอร์เนลและพื้นที่ส่วนใหญ่นี้ถูกแมปไปยังตำแหน่งเริ่มต้นของหน่วยความจำกายภาพที่มีการโหลดอิมเมจเคอร์เนลในเวลาบูต
ขนาดพื้นที่สูงสุดของแอดเดรสขึ้นอยู่กับความยาวของแอดเดรสที่ลงทะเบียนบน CPU
บนระบบที่มีการลงทะเบียนที่อยู่แบบ 32 บิตขนาดของพื้นที่ที่อยู่สูงสุดคือ 2 32ไบต์หรือ 4 GiB ในทำนองเดียวกันบนระบบ64บิตสามารถระบุ2 2 ไบต์ได้
พื้นที่ที่อยู่ดังกล่าวเรียกว่าหน่วยความจำเสมือนหรือพื้นที่ที่อยู่เสมือน ไม่เกี่ยวข้องกับขนาด RAM จริง
บนแพลตฟอร์ม Linux พื้นที่ที่อยู่เสมือนจะแบ่งออกเป็นพื้นที่เคอร์เนลและพื้นที่ผู้ใช้
ค่าคงที่เฉพาะสถาปัตยกรรมที่เรียกว่าขีด จำกัด ขนาดงานหรือTASK_SIZE
ทำเครื่องหมายตำแหน่งที่เกิดการแยก:
ช่วงที่อยู่ตั้งแต่ 0 ถึงTASK_SIZE
-1 ถูกจัดสรรให้กับพื้นที่ผู้ใช้
ส่วนที่เหลือจากTASK_SIZE
สูงสุด 2 32 -1 (หรือ 2 64 -1) จะถูกจัดสรรให้กับพื้นที่เคอร์เนล
ตัวอย่างเช่นระบบ 32 บิตเฉพาะ 3 GiB อาจครอบครองพื้นที่ผู้ใช้และ 1 GiB สำหรับพื้นที่เคอร์เนล
แต่ละแอปพลิเคชั่น / โปรแกรมในระบบปฏิบัติการ Unix-like นั้นเป็นกระบวนการหนึ่ง แต่ละตัวมีตัวระบุเฉพาะที่เรียกว่า Process Identifier (หรือเพียงแค่ID กระบวนการเช่น PID) Linux จัดเตรียมสองกลไกสำหรับการสร้างกระบวนการ: 1. การfork()
เรียกของระบบหรือ 2. การexec()
เรียก
เคอร์เนลเธรดเป็นกระบวนการที่มีน้ำหนักเบาและโปรแกรมภายใต้การดำเนินการ กระบวนการเดียวอาจประกอบด้วยหลายเธรดที่แชร์ข้อมูลและทรัพยากรเดียวกัน แต่ใช้เส้นทางที่แตกต่างกันผ่านรหัสโปรแกรม Linux จัดเตรียมการclone()
เรียกระบบเพื่อสร้างเธรด
ตัวอย่างการใช้เคอร์เนลเธรดคือ: การซิงโครไนซ์ข้อมูลของ RAM ช่วยให้ตัวกำหนดตารางเวลาเพื่อแจกจ่ายกระบวนการระหว่างซีพียู ฯลฯ
สั้น ๆ : เคอร์เนลทำงานในพื้นที่เคอร์เนลพื้นที่เคอร์เนลมีการเข้าถึงหน่วยความจำและทรัพยากรทั้งหมดคุณสามารถพูดได้ว่าหน่วยความจำแบ่งออกเป็นสองส่วนส่วนหนึ่งสำหรับเคอร์เนลและส่วนหนึ่งสำหรับกระบวนการของผู้ใช้ (พื้นที่ผู้ใช้) รันโปรแกรมปกติผู้ใช้ พื้นที่ไม่สามารถเข้าถึงโดยตรงไปยังพื้นที่เคอร์เนลดังนั้นจึงขอจากเคอร์เนลเพื่อใช้ทรัพยากร โดย syscall (การโทรของระบบที่กำหนดไว้ล่วงหน้าเป็น glibc)
มีคำสั่งที่ทำให้ " พื้นที่ผู้ใช้เป็นเพียงการทดสอบโหลดสำหรับเคอร์เนล " ที่แตกต่างกันคือ ...
มีความชัดเจนมาก: สถาปัตยกรรมโปรเซสเซอร์อนุญาตให้ CPU ทำงานในสองโหมดคือโหมดเคอร์เนลและโหมดผู้ใช้คำสั่งฮาร์ดแวร์อนุญาตให้สลับจากโหมดหนึ่งไปเป็นโหมดอื่น
หน่วยความจำสามารถทำเครื่องหมายว่าเป็นส่วนหนึ่งของพื้นที่ผู้ใช้หรือพื้นที่เคอร์เนล
เมื่อ CPU ทำงานในโหมดผู้ใช้ CPU สามารถเข้าถึงเฉพาะหน่วยความจำที่อยู่ในพื้นที่ผู้ใช้ในขณะที่ cpu พยายามเข้าถึงหน่วยความจำในพื้นที่เคอร์เนลผลลัพธ์คือ "ข้อยกเว้นฮาร์ดแวร์" เมื่อ CPU ทำงานในโหมดเคอร์เนล CPU สามารถเข้าถึงได้โดยตรง ไปที่พื้นที่เคอร์เนลและพื้นที่ผู้ใช้ ...
พื้นที่เคอร์เนลหมายถึงพื้นที่หน่วยความจำสามารถสัมผัสโดยเคอร์เนลเท่านั้น บน 32 บิตลินุกซ์มันเป็น 1G (จาก 0xC0000000 ถึง 0xffffffff เป็นที่อยู่หน่วยความจำเสมือน) ทุกกระบวนการที่สร้างโดยเคอร์เนลยังเป็นเคอร์เนลเธรดดังนั้นสำหรับหนึ่งกระบวนการมีสองสแต็ก: สแต็กหนึ่งในพื้นที่ผู้ใช้สำหรับกระบวนการนี้ พื้นที่สำหรับเคอร์เนลเธรด
เคอร์เนลสแต็คครอบครอง 2 หน้า (8k ใน 32 บิตลินุกซ์) รวม task_struct (ประมาณ 1k) และกองจริง (ประมาณ 7k) หลังถูกใช้เพื่อเก็บตัวแปรอัตโนมัติหรือพารามิเตอร์การเรียกฟังก์ชันหรือที่อยู่ฟังก์ชันในฟังก์ชันเคอร์เนล นี่คือรหัส (Processor.h (linux \ include \ asm-i386)):
#define THREAD_SIZE (2*PAGE_SIZE)
#define alloc_task_struct() ((struct task_struct *) __get_free_pages(GFP_KERNEL,1))
#define free_task_struct(p) free_pages((unsigned long) (p), 1)
__get_free_pages (GFP_KERNEL, 1)) หมายถึงจัดสรรหน่วยความจำเป็น 2 ^ 1 = 2 หน้า
แต่กระบวนการสแต็กเป็นอีกสิ่งหนึ่งที่อยู่ของมันเป็นเพียงการร้อง 0xC0000000 (32 บิตลินุกซ์) ขนาดของมันจะค่อนข้างใหญ่ใช้สำหรับการเรียกใช้ฟังก์ชันพื้นที่ของผู้ใช้
ดังนั้นนี่คือคำถามสำหรับการเรียกระบบมันทำงานในพื้นที่เคอร์เนล แต่ถูกเรียกโดยกระบวนการในพื้นที่ผู้ใช้มันทำงานอย่างไร linux จะใส่พารามิเตอร์และที่อยู่ฟังก์ชันไว้ใน kernel stack หรือ process stack หรือไม่? โซลูชันของ Linux: การเรียกใช้ระบบทั้งหมดเกิดขึ้นจากการหยุดชะงักของซอฟต์แวร์ INT 0x80 กำหนดไว้ในรายการ S (linux \ arch \ i386 \ kernel) นี่คือตัวอย่างบางบรรทัด:
ENTRY(sys_call_table)
.long SYMBOL_NAME(sys_ni_syscall) /* 0 - old "setup()" system call*/
.long SYMBOL_NAME(sys_exit)
.long SYMBOL_NAME(sys_fork)
.long SYMBOL_NAME(sys_read)
.long SYMBOL_NAME(sys_write)
.long SYMBOL_NAME(sys_open) /* 5 */
.long SYMBOL_NAME(sys_close)
เคอร์เนล Linux หมายถึงทุกสิ่งที่ทำงานในโหมดเคอร์เนลและประกอบด้วยเลเยอร์ที่แตกต่างกันหลายอย่าง ที่เลเยอร์ต่ำสุดเคอร์เนลโต้ตอบกับฮาร์ดแวร์ผ่าน HAL ในระดับกลางเคอร์เนล UNIX จะถูกแบ่งออกเป็น 4 ส่วน ครั้งแรกของทั้งสี่พื้นที่จัดการอุปกรณ์ตัวอักษร TTY ดิบและสุกและการจัดการขั้ว พื้นที่ที่สองจัดการไดรเวอร์อุปกรณ์เครือข่ายโปรโตคอลเส้นทางและซ็อกเก็ต พื้นที่ที่สามจัดการไดรเวอร์อุปกรณ์ดิสก์แคชหน้าและบัฟเฟอร์ระบบไฟล์หน่วยความจำเสมือนการตั้งชื่อไฟล์และการแมป พื้นที่ที่สี่และสุดท้ายจัดการกระบวนการการจัดกำหนดการการสร้างและการเลิกจ้างรวมถึงการจัดการสัญญาณ เหนือสิ่งอื่นใดเรามีเลเยอร์บนสุดของเคอร์เนลซึ่งรวมถึงการเรียกระบบการขัดจังหวะและกับดัก ระดับนี้ทำหน้าที่เป็นอินเทอร์เฟซสำหรับแต่ละฟังก์ชั่นระดับล่าง โปรแกรมเมอร์ใช้การเรียกของระบบและการขัดจังหวะต่าง ๆ เพื่อโต้ตอบกับคุณลักษณะของระบบปฏิบัติการ
ในพื้นที่เคอร์เนลแบบสั้นคือส่วนของหน่วยความจำที่เคอร์เนล linux รัน (พื้นที่ว่างบนสุด 1 GB ในกรณีของ linux) และพื้นที่ผู้ใช้เป็นส่วนของหน่วยความจำที่แอปพลิเคชันของผู้ใช้ทำงาน (ด้านล่าง 3 GB ของหน่วยความจำเสมือนในกรณีของ Linux หากคุณ ต้องการทราบข้อมูลเพิ่มเติมดูลิงค์ด้านล่าง :)
http://learnlinuxconcepts.blogspot.in/2014/02/kernel-space-and-user-space.html
พยายามที่จะให้คำอธิบายที่ง่ายมาก
หน่วยความจำเสมือนแบ่งออกเป็นพื้นที่เคอร์เนลและพื้นที่ผู้ใช้ พื้นที่เคอร์เนลคือพื้นที่ของหน่วยความจำเสมือนที่กระบวนการเคอร์เนลจะทำงานและพื้นที่ผู้ใช้เป็นพื้นที่ของหน่วยความจำเสมือนที่กระบวนการของผู้ใช้จะทำงาน
การแบ่งนี้จำเป็นสำหรับการป้องกันการเข้าถึงหน่วยความจำ
เมื่อใดก็ตามที่ bootloader เริ่มต้นเคอร์เนลหลังจากโหลดไปยังตำแหน่งใน RAM (โดยทั่วไปจะใช้คอนโทรลเลอร์ ARM) จะต้องตรวจสอบให้แน่ใจว่าคอนโทรลเลอร์อยู่ในโหมดผู้ดูแลระบบซึ่งปิดการใช้งานของ FIQ และ IRQ
พื้นที่เคอร์เนลและพื้นที่ผู้ใช้เป็นพื้นที่ตรรกะ
โปรเซสเซอร์ที่ทันสมัยส่วนใหญ่ได้รับการออกแบบให้ทำงานในโหมดสิทธิพิเศษที่แตกต่างกัน เครื่อง x86 สามารถทำงานในโหมดพิเศษ 4 โหมด
และคำสั่งเครื่องโดยเฉพาะสามารถดำเนินการได้เมื่ออยู่ใน / เหนือโหมดสิทธิพิเศษ
เนื่องจากการออกแบบนี้คุณจะให้การป้องกันระบบหรือทรายมวยสภาพแวดล้อมการดำเนินการ
เคอร์เนลเป็นส่วนหนึ่งของรหัสซึ่งจัดการฮาร์ดแวร์ของคุณและให้ระบบที่เป็นนามธรรม ดังนั้นจึงจำเป็นต้องมีการเข้าถึงสำหรับคำสั่งเครื่องทั้งหมด และเป็นซอฟต์แวร์ที่เชื่อถือได้มากที่สุด ดังนั้นฉันควรจะดำเนินการด้วยสิทธิพิเศษสูงสุด และระดับวงแหวน 0เป็นโหมดที่ได้รับสิทธิพิเศษมากที่สุด ดังนั้นแหวนระดับ 0จะเรียกว่าเป็นโหมดเคอร์เนล
แอปพลิเคชันผู้ใช้เป็นชิ้นส่วนของซอฟต์แวร์ที่มาจากผู้จำหน่ายบุคคลที่สามและคุณไม่สามารถเชื่อถือได้อย่างสมบูรณ์ คนที่มีเจตนาร้ายสามารถเขียนรหัสเพื่อให้ระบบของคุณพังได้หากเขาสามารถเข้าถึงคำสั่งเครื่องทั้งหมดได้ ดังนั้นแอปพลิเคชันควรได้รับการเข้าถึงชุดคำสั่งที่ จำกัด และแหวนระดับ 3เป็นโหมดที่ได้รับสิทธิน้อยที่สุด ดังนั้นแอปพลิเคชันทั้งหมดของคุณจะทำงานในโหมดนั้น ดังนั้นที่แหวน Level 3จะเรียกว่าผู้ใช้โหมด
หมายเหตุ: ฉันไม่ได้รับ Ring Level 1 และ 2 พวกเขาเป็นโหมดที่มีสิทธิ์ระดับกลาง ดังนั้นอาจมีการเรียกใช้รหัสไดรเวอร์อุปกรณ์ด้วยสิทธิ์นี้ AFAIK, linux ใช้เฉพาะระดับวงแหวน 0 และ 3 สำหรับการเรียกใช้โค้ดเคอร์เนลและแอปพลิเคชันผู้ใช้ตามลำดับ
ดังนั้นการดำเนินการใด ๆ ที่เกิดขึ้นในโหมดเคอร์เนลถือได้ว่าเป็นพื้นที่เคอร์เนล และการดำเนินการใด ๆ ที่เกิดขึ้นในโหมดผู้ใช้ถือได้ว่าเป็นพื้นที่ผู้ใช้
คำตอบที่ถูกต้องคือ: ไม่มีสิ่งเช่นพื้นที่เคอร์เนลและพื้นที่ผู้ใช้ ชุดคำสั่งตัวประมวลผลมีสิทธิ์พิเศษในการตั้งค่าสิ่งที่ทำลายล้างเช่นรูทของแผนที่ตารางหน้าหรือเข้าถึงหน่วยความจำอุปกรณ์ฮาร์ดแวร์ ฯลฯ
รหัสเคอร์เนลมีสิทธิ์ระดับสูงสุดและรหัสผู้ใช้ต่ำสุด สิ่งนี้จะช่วยป้องกันไม่ให้รหัสผู้ใช้ขัดข้องระบบการแก้ไขโปรแกรมอื่น ๆ
โดยทั่วไปรหัสเคอร์เนลจะถูกเก็บไว้ในแผนที่หน่วยความจำที่แตกต่างจากรหัสผู้ใช้ (เช่นเดียวกับพื้นที่ผู้ใช้จะถูกเก็บไว้ในแผนที่หน่วยความจำที่แตกต่างกันกว่ากัน) นี่คือที่มาของคำว่า "kernel space" และ "space space" แต่นั่นไม่ใช่กฎที่ยากและรวดเร็ว ตัวอย่างเช่นเนื่องจาก x86 ทางอ้อมต้องการให้ตัวจัดการอินเตอร์รัปต์ / กับดักถูกแมปตลอดเวลาจึงต้องทำการแมป (หรือบางระบบปฏิบัติการทั้งหมด) ของเคอร์เนลลงในพื้นที่ผู้ใช้ อีกครั้งนี้ไม่ได้หมายความว่ารหัสดังกล่าวมีสิทธิ์ผู้ใช้
เหตุใดเคอร์เนล / ผู้ใช้จึงมีความจำเป็น นักออกแบบบางคนไม่เห็นด้วยว่าจำเป็นจริงๆ สถาปัตยกรรม Microkernel ขึ้นอยู่กับแนวคิดที่ว่าส่วนของรหัสที่มีสิทธิ์สูงสุดควรมีขนาดเล็กที่สุดเท่าที่จะเป็นไปได้โดยมีการดำเนินการที่สำคัญทั้งหมดในรหัสสิทธิ์ของผู้ใช้ คุณจะต้องศึกษาว่าทำไมสิ่งนี้จึงเป็นความคิดที่ดีไม่ใช่แนวคิดง่าย ๆ (และมีชื่อเสียงทั้งในเรื่องข้อดีและข้อเสีย)
การรับหน่วยความจำแบ่งออกเป็นสองส่วน:
กระบวนการที่ทำงานภายใต้พื้นที่ผู้ใช้สามารถเข้าถึงหน่วยความจำส่วนที่ จำกัด เท่านั้นในขณะที่เคอร์เนลมีการเข้าถึงหน่วยความจำทั้งหมด กระบวนการที่ทำงานในพื้นที่ของผู้ใช้ยังไม่สามารถเข้าถึงพื้นที่เคอร์เนลได้ กระบวนการพื้นที่ของผู้ใช้สามารถเข้าถึงส่วนเล็ก ๆ ของเคอร์เนลผ่านส่วนต่อประสานที่สัมผัสโดยเคอร์เนล - การเรียกของระบบหากกระบวนการทำการเรียกระบบระบบจะส่งซอฟต์แวร์ขัดจังหวะไปยังเคอร์เนลซึ่งจะส่งตัวจัดการอินเตอร์รัปต์ที่เหมาะสม การทำงานหลังจากที่ตัวจัดการเสร็จสิ้น
ในลีนุกซ์มีสองสเปซที่หนึ่งคือสเปซของผู้ใช้และสเปซอื่นคือ kernal space พื้นที่ผู้ใช้ประกอบด้วยแอปพลิเคชันผู้ใช้เท่านั้นที่คุณต้องการเรียกใช้ เนื่องจากบริการ kernal มีการจัดการกระบวนการ, การจัดการไฟล์, การจัดการสัญญาณ, การจัดการหน่วยความจำ, การจัดการเธรดและบริการมากมายที่มีอยู่ในนั้น หากคุณเรียกใช้แอปพลิเคชันจากพื้นที่ผู้ใช้ที่การตอบสนองต่อการสมัครบริการ kernal เท่านั้น และบริการนั้นมีการโต้ตอบกับไดรเวอร์อุปกรณ์ซึ่งอยู่ระหว่างฮาร์ดแวร์และ kernal ประโยชน์หลักของพื้นที่ kernal และการแยกพื้นที่ผู้ใช้คือเราสามารถรับความปลอดภัยโดย virus.bcaz ของแอปพลิเคชันผู้ใช้ทั้งหมดที่มีอยู่ในพื้นที่ของผู้ใช้และบริการอยู่ในพื้นที่ kernal นั่นเป็นเหตุผลว่าทำไม linux จึงไม่ได้รับผลกระทบจากไวรัส