อะไรคือความแตกต่างระหว่าง kernel stack และ user stack? เหตุใดจึงใช้เคอร์เนลสแต็ก หากมีการประกาศตัวแปรภายในใน ISR จะเก็บไว้ที่ใด แต่ละกระบวนการมี kernel stack ของตัวเองหรือไม่? แล้วกระบวนการประสานงานระหว่างทั้งสองกองนี้อย่างไร?
อะไรคือความแตกต่างระหว่าง kernel stack และ user stack? เหตุใดจึงใช้เคอร์เนลสแต็ก หากมีการประกาศตัวแปรภายในใน ISR จะเก็บไว้ที่ใด แต่ละกระบวนการมี kernel stack ของตัวเองหรือไม่? แล้วกระบวนการประสานงานระหว่างทั้งสองกองนี้อย่างไร?
คำตอบ:
- อะไรคือความแตกต่างระหว่าง kernel stack และ user stack?
ในระยะสั้นไม่มีอะไรนอกเหนือจากการใช้ตำแหน่งอื่นในหน่วยความจำ (และด้วยเหตุนี้ค่าที่แตกต่างกันสำหรับการลงทะเบียน stackpointer) และโดยปกติแล้วการป้องกันการเข้าถึงหน่วยความจำที่แตกต่างกัน กล่าวคือเมื่อดำเนินการในโหมดผู้ใช้หน่วยความจำเคอร์เนล (ซึ่งเป็นส่วนหนึ่งของเคอร์เนลสแต็ก) จะไม่สามารถเข้าถึงได้แม้ว่าจะแมป ในทางกลับกันโดยที่รหัสเคอร์เนลไม่ได้รับการร้องขออย่างชัดเจน (ใน Linux ผ่านฟังก์ชันเช่นcopy_from_user()
) หน่วยความจำผู้ใช้ (รวมถึงสแตกผู้ใช้) มักจะไม่สามารถเข้าถึงได้โดยตรง
- เหตุใดจึงใช้สแต็กเคอร์เนล [แยก]
การแยกสิทธิพิเศษและความปลอดภัย ประการแรกโปรแกรม userspace สามารถสร้าง stack (ตัวชี้) ได้ทุกอย่างที่ต้องการและโดยปกติแล้วไม่มีข้อกำหนดทางสถาปัตยกรรมใด ๆ ที่จะต้องมีโปรแกรมที่ถูกต้อง ดังนั้นเคอร์เนลจึงไม่สามารถไว้วางใจให้ userspace stackpointer ถูกต้องหรือใช้งานได้ดังนั้นจึงต้องใช้ชุดเดียวภายใต้การควบคุมของตัวเอง สถาปัตยกรรมซีพียูที่แตกต่างกันใช้สิ่งนี้ในรูปแบบที่แตกต่างกัน x86 ซีพียูจะสลับสแต็กพอยต์เตอร์โดยอัตโนมัติเมื่อเกิดการสลับโหมดสิทธิ์และค่าที่จะใช้สำหรับระดับสิทธิ์ที่แตกต่างกันนั้นสามารถกำหนดค่าได้โดยใช้รหัสพิเศษ (เช่นเฉพาะเคอร์เนล)
- หากมีการประกาศตัวแปรภายในใน ISR จะเก็บไว้ที่ใด
บนกองเคอร์เนล เคอร์เนล (เคอร์เนลลินุกซ์นั่นคือ) ไม่เชื่อมโยง ISR โดยตรงกับประตูขัดจังหวะของสถาปัตยกรรม x86 แต่จะมอบหมายการส่งการขัดจังหวะไปยังกลไกการเข้า / ออกจากการขัดจังหวะเคอร์เนลทั่วไปซึ่งจะบันทึกสถานะการลงทะเบียนล่วงหน้าก่อนที่จะเรียกตัวจัดการที่ลงทะเบียน . ตัว CPU เองเมื่อส่งการขัดจังหวะอาจเรียกใช้สิทธิ์และ / หรือสวิตช์สแต็กและสิ่งนี้ถูกใช้ / ตั้งค่าโดยเคอร์เนลเพื่อให้โค้ดรายการอินเตอร์รัปต์ทั่วไปสามารถพึ่งพาสแต็กเคอร์เนลที่มีอยู่แล้ว
ที่กล่าวว่าการขัดจังหวะที่เกิดขึ้นในขณะเรียกใช้รหัสเคอร์เนลจะเพียงแค่ (ดำเนินการต่อไป) โดยใช้เคอร์เนลสแต็กที่จุดนั้น สิ่งนี้สามารถหากตัวจัดการการขัดจังหวะมีเส้นทางการโทรที่ซ้อนกันอย่างลึกล้ำนำไปสู่การล้นสแต็ก (หากเส้นทางการเรียกเคอร์เนลแบบลึกถูกขัดจังหวะและตัวจัดการทำให้เกิดเส้นทางลึกอื่นใน Linux รหัส RAID ของระบบไฟล์ / ซอฟต์แวร์ที่ถูกขัดจังหวะโดยรหัสเครือข่ายที่มี iptables ที่ใช้งานอยู่คือ เป็นที่ทราบกันดีว่าจะทริกเกอร์เช่นนี้ในเมล็ดพันธุ์เก่าที่ไม่ได้ปรับแต่ง ... วิธีแก้ปัญหาคือการเพิ่มขนาดเคอร์เนลสแต็กสำหรับปริมาณงานดังกล่าว)
- แต่ละกระบวนการมี kernel stack ของตัวเองหรือไม่?
ไม่ใช่แค่แต่ละกระบวนการ - แต่ละเธรดมีสแต็กเคอร์เนลของตัวเอง (และในความเป็นจริงสแต็กผู้ใช้ของตัวเองเช่นกัน) โปรดจำไว้ว่าข้อแตกต่างเพียงอย่างเดียวระหว่างกระบวนการและเธรด (สำหรับ Linux) คือความจริงที่ว่าเธรดหลายเธรดสามารถใช้พื้นที่แอดเดรสร่วมกันได้ (สร้างกระบวนการ)
- กระบวนการประสานงานระหว่างสแต็กทั้งสองนี้อย่างไร?
ไม่เลย - ไม่จำเป็นต้องทำ การจัดกำหนดการ (วิธีการ / เมื่อเธรดที่แตกต่างกันกำลังถูกเรียกใช้สถานะของพวกเขาถูกบันทึกและเรียกคืนอย่างไร) เป็นงานและกระบวนการของระบบปฏิบัติการไม่จำเป็นต้องกังวลกับสิ่งนี้ เมื่อเธรดถูกสร้างขึ้น (และแต่ละกระบวนการต้องมีเธรดอย่างน้อยหนึ่งเธรด) เคอร์เนลจะสร้างสแต็กเคอร์เนลสำหรับพวกเขาในขณะที่สแต็ก userspace ถูกสร้างขึ้นอย่างชัดเจน / จัดเตรียมโดยกลไกใดก็ตามที่ใช้ในการสร้างเธรด (ฟังก์ชันเช่นmakecontext()
หรือpthread_create()
อนุญาตให้ผู้เรียกใช้ ระบุขอบเขตหน่วยความจำที่จะใช้สำหรับสแต็กของเธรด "ชายด์") หรือรับช่วง (โดยการโคลนหน่วยความจำที่เข้าถึงโดยปกติเรียกว่า "copy on write" / COW เมื่อสร้างกระบวนการใหม่)
ที่กล่าวว่า(สถานะในนั้นคือสแต็กพอยน์เตอร์ของเธรด) มีหลายวิธีสำหรับสิ่งนี้: สัญญาณ UNIX setcontext()
,, pthread_yield()
/ pthread_cancel()
, ... - แต่นี่เป็นการขัดข้องเล็กน้อยจากคำถามเดิม
คำตอบของฉันรวบรวมจากคำถาม SO อื่น ๆ ที่มีเนื้อหาของฉัน
What's the difference between kernel stack and user stack?
ในฐานะโปรแกรมเมอร์เคอร์เนลคุณทราบดีว่าควร จำกัด เคอร์เนลจากโปรแกรมผู้ใช้ที่ผิดพลาด สมมติว่าคุณเก็บสแต็กเดียวกันสำหรับทั้งเคอร์เนลและพื้นที่ผู้ใช้จากนั้น segfault อย่างง่ายในแอปพลิเคชันผู้ใช้ทำให้เคอร์เนลล่มและต้องรีสตาร์ท
มี "เคอร์เนลสแต็ก" หนึ่งรายการต่อ CPU เช่น ISR Stack และหนึ่ง "kernel stack" ต่อหนึ่งกระบวนการ มี "สแต็กผู้ใช้" หนึ่งรายการสำหรับแต่ละกระบวนการแม้ว่าแต่ละเธรดจะมีสแต็กของตัวเองรวมทั้งเธรดผู้ใช้และเคอร์เนล
http://linux.derkeiler.com/Mailing-Lists/Kernel/2004-10/3194.html
Why kernel stack is used?
ดังนั้นเมื่อเราอยู่ในโหมดเคอร์เนลกลไกประเภทสแต็กจึงจำเป็นสำหรับการจัดการกับการเรียกใช้ฟังก์ชันตัวแปรโลคัลที่คล้ายกับพื้นที่ของผู้ใช้
http://www.kernel.org/doc/Documentation/x86/kernel-stacks
If a local variable is declared in an ISR, where it will be stored?
จะถูกเก็บไว้ใน ISR stack (IRQSTACKSIZE) ISR จะทำงานบนอินเตอร์รัปต์สแต็กที่แยกจากกันเฉพาะในกรณีที่ฮาร์ดแวร์รองรับเท่านั้น มิฉะนั้นเฟรมสแต็ก ISR จะถูกดันไปที่สแต็กของเธรดที่ถูกขัดจังหวะ
พื้นที่ผู้ใช้ไม่ทราบและโดยตรงไปตรงมาไม่สนใจว่าการขัดจังหวะจะถูกเสิร์ฟในสแต็กเคอร์เนลของกระบวนการปัจจุบันหรือสแตก ISR แยกต่างหาก เมื่ออินเทอร์รัปต์มาต่อซีพียูดังนั้น ISR stack จึงต้องเป็นต่อ cpu
Does each process has its own kernel stack ?
ใช่. แต่ละกระบวนการมีกองเคอร์เนลของตัวเอง
Then how the process coordinates between both these stacks?
คำตอบของ @ FrankH ดูดีสำหรับฉัน
- อะไรคือความแตกต่างระหว่าง kernel stack และ user stack
อ้างอิงจากการพัฒนาเคอร์เนลลินุกซ์ของ Robert Love ความแตกต่างที่สำคัญคือขนาด:
พื้นที่ผู้ใช้สามารถหลีกเลี่ยงได้ด้วยการจัดสรรตัวแปรจำนวนมากบนสแต็กแบบคงที่รวมถึงโครงสร้างขนาดใหญ่และอาร์เรย์หลายพันองค์ประกอบ
พฤติกรรมนี้ถูกกฎหมายเนื่องจากพื้นที่ผู้ใช้มีสแต็กขนาดใหญ่ที่สามารถเติบโตแบบไดนามิก
สแต็กเคอร์เนลไม่มีขนาดใหญ่หรือไดนามิก มีขนาดเล็กและมีขนาดคงที่
ขนาดที่แน่นอนของสแต็กของเคอร์เนลจะแตกต่างกันไปตามสถาปัตยกรรม
บน x86 ขนาดสแต็กสามารถกำหนดค่าได้ในเวลาคอมไพล์และสามารถเป็น 4KB หรือ 8KB
ในอดีตสแต็กเคอร์เนลมีสองหน้าซึ่งโดยทั่วไปหมายความว่าเป็น 8KB บนสถาปัตยกรรม 32 บิตและ 16KB สำหรับสถาปัตยกรรม 64 บิตขนาดนี้ได้รับการแก้ไขและสัมบูรณ์
แต่ละกระบวนการได้รับสแตกของตัวเอง
นอกจากนี้สแต็กเคอร์เนลยังมีตัวชี้ไปยังข้อมูลที่เก็บโครงสร้าง thread_info เกี่ยวกับเธรด