อ่าน 6 นาที
ระบบรันไทม์
ใน การเขียนโปรแกรมคอมพิวเตอร์ ระบบ รันไทม์ หรือเรียกสั้นๆ ว่า รันไทม์ คือระบบย่อยที่มีอยู่ในคอมพิวเตอร์ที่สร้างโปรแกรม รวมถึงในคอมพิวเตอร์ที่ตั้งใจจะรันโปรแกรม ชื่อนี้มาจากการ...
ระบบรันไทม์
| การดำเนินการตามโปรแกรม |
|---|
| แนวคิดทั่วไป |
| ประเภทของโค้ด |
| กลยุทธ์การรวบรวม |
| ระยะเวลาการวิ่งที่น่าสนใจ |
|
| คอมไพเลอร์และชุดเครื่องมือที่โดดเด่น |
ในการเขียนโปรแกรมคอมพิวเตอร์ระบบรันไทม์หรือเรียกสั้นๆ ว่ารันไทม์คือระบบย่อยที่มีอยู่ในคอมพิวเตอร์ที่สร้างโปรแกรม รวมถึงในคอมพิวเตอร์ที่ตั้งใจจะรันโปรแกรม ชื่อนี้มาจากการ แบ่ง เวลาคอมไพล์และเวลารันไทม์จากภาษาคอมไพล์ซึ่งแยกแยะกระบวนการคอมพิวเตอร์ที่เกี่ยวข้องกับการสร้างโปรแกรม (การคอมไพล์) และการดำเนินการในเครื่องเป้าหมาย (รันไทม์) ในลักษณะเดียวกัน[ 1 ]สภาพแวดล้อมรันไทม์ (RTE) คือบริบทที่รันไทม์ทำงาน
ภาษาโปรแกรมส่วนใหญ่มีระบบรันไทม์บางรูปแบบที่ให้สภาพแวดล้อมในการทำงานของโปรแกรม สภาพแวดล้อมนี้อาจจัดการกับปัญหาหลายประการ รวมถึงการจัดการหน่วยความจำของแอปพลิเค ชัน วิธีที่โปรแกรมเข้าถึงตัวแปรกลไกสำหรับการส่งผ่านพารามิเตอร์ระหว่างขั้นตอนการเชื่อมต่อกับระบบปฏิบัติการ (OS) และอื่นๆคอมไพเลอร์จะตั้งสมมติฐานขึ้นอยู่กับระบบรันไทม์เฉพาะเพื่อสร้างโค้ดที่ถูกต้อง โดยทั่วไป ระบบรันไทม์จะมีหน้าที่ในการตั้งค่าและจัดการสแต็กและฮีปและอาจรวมถึงคุณสมบัติต่างๆ เช่นการเก็บขยะเธรดหรือ คุณสมบัติ แบบไดนามิกอื่นๆที่สร้างขึ้นในภาษา[ 1 ]
ภาพรวม
ทุกภาษาโปรแกรมกำหนดรูปแบบการทำงานและหลายภาษาใช้ระบบรันไทม์อย่างน้อยบางส่วนในการนำรูปแบบนั้นไปใช้ หนึ่งในนิยามที่เป็นไปได้ของพฤติกรรมระบบรันไทม์คือ "พฤติกรรมใดๆ ที่ไม่ได้เกิดจากโปรแกรมโดยตรง" นิยามนี้รวมถึงการวางพารามิเตอร์ลงบนสแต็กก่อนเรียกฟังก์ชัน การทำงานแบบขนานของพฤติกรรมที่เกี่ยวข้อง และการอ่าน/เขียนข้อมูลจากดิสก์
ตามคำจำกัดความนี้ โดยพื้นฐานแล้วทุกภาษามีระบบรันไทม์ รวมถึงภาษาคอมไพล์ภาษาอินเตอร์พรีเตอร์และภาษาเฉพาะโดเมนแบบฝังตัวแม้แต่ โมเดลการทำงานแบบสแตนด์อโลนที่เรียกใช้ผ่าน APIเช่นPthreads ( เธรดPOSIX ) ก็มีระบบรันไทม์ที่ใช้ในการทำงานของโมเดลนั้น ๆ
เอกสารวิชาการส่วนใหญ่เกี่ยวกับระบบรันไทม์มุ่งเน้นไปที่รายละเอียดการใช้งานของระบบรันไทม์แบบขนาน ตัวอย่างที่โดดเด่นของระบบรันไทม์แบบขนานคือCilkซึ่งเป็นแบบจำลองการเขียนโปรแกรมแบบขนานที่ได้รับความนิยม[ 2 ]ชุดเครื่องมือ proto-runtime ถูกสร้างขึ้นเพื่อลดความซับซ้อนในการสร้างระบบรันไทม์แบบขนาน[ 3 ]
นอกเหนือจากพฤติกรรมของโมเดลการดำเนินการแล้ว ระบบรันไทม์ยังอาจให้บริการสนับสนุน เช่นการตรวจสอบประเภทการดีบักหรือการสร้างโค้ดและการเพิ่มประสิทธิภาพ[ 4 ]
| พิมพ์ | คำอธิบาย | ตัวอย่าง |
|---|---|---|
| สภาพแวดล้อมรันไทม์ | แพลตฟอร์มซอฟต์แวร์ที่จัดเตรียมสภาพแวดล้อมสำหรับการเรียกใช้โค้ด | Node.js , .NET Framework , StoffelVM [ 5 ] |
| เครื่องยนต์ | ส่วนประกอบของสภาพแวดล้อมการทำงานที่ประมวลผลโค้ดโดยการคอมไพล์หรือตีความโค้ดนั้น | กลไก JavaScriptในเว็บเบราว์เซอร์, เครื่องเสมือน Java |
| ล่าม | ประเภทของเอนจิ้นที่อ่านและประมวลผลโค้ดทีละบรรทัด โดยไม่ต้องคอมไพล์โปรแกรมทั้งหมดล่วงหน้า | ตัวแปลภาษา CPython , Ruby MRI , JavaScript (ในบางกรณี) |
| ล่าม JIT | ประเภทของตัวแปลภาษาที่คอมไพล์โค้ดเป็นคำสั่งเครื่องแบบไดนามิกในระหว่างการทำงาน โดยปรับแต่งโค้ดเพื่อให้ประมวลผลได้เร็วขึ้น | V8 , ตัวแปลภาษา PyPy |
ความสัมพันธ์กับสภาพแวดล้อมขณะทำงาน
ระบบรันไทม์เป็นเสมือนประตูที่โปรแกรมที่กำลังทำงานอยู่ใช้ในการโต้ตอบกับสภาพแวดล้อมรันไทม์สภาพแวดล้อมรันไทม์ไม่เพียงแต่รวมถึงค่าสถานะที่เข้าถึงได้เท่านั้น แต่ยังรวมถึงเอนทิตีที่ทำงานได้ซึ่งโปรแกรมสามารถโต้ตอบด้วยในระหว่างการทำงาน ตัวอย่างเช่นตัวแปรสภาพแวดล้อมเป็นคุณสมบัติของระบบปฏิบัติการหลายระบบ และเป็นส่วนหนึ่งของสภาพแวดล้อมรันไทม์ โปรแกรมที่กำลังทำงานอยู่สามารถเข้าถึงตัวแปรเหล่านี้ได้ผ่านทางระบบรันไทม์ ในทำนองเดียวกัน อุปกรณ์ฮาร์ดแวร์ เช่น ดิสก์หรือไดรฟ์ DVD ก็เป็นเอนทิตีที่ทำงานได้ซึ่งโปรแกรมสามารถโต้ตอบด้วยผ่านทางระบบรันไทม์
การใช้งานสภาพแวดล้อมรันไทม์ที่เป็นเอกลักษณ์อย่างหนึ่งคือการใช้งานภายในระบบปฏิบัติการที่ อนุญาตให้ เฉพาะสภาพแวดล้อมนั้นทำงานได้เท่านั้น กล่าวคือ ตั้งแต่เริ่มบูตจนถึงปิดเครื่อง ระบบปฏิบัติการทั้งหมดจะถูกใช้งานโดยแอปพลิเคชันที่ทำงานอยู่ภายในสภาพแวดล้อมรันไทม์นั้นเพียงอย่างเดียว โค้ดอื่นๆ ที่พยายามทำงาน หรือความล้มเหลวใดๆ ในแอปพลิเคชัน จะทำให้สภาพแวดล้อมรันไทม์เสียหาย การที่สภาพแวดล้อมรันไทม์เสียหายจะทำให้ระบบปฏิบัติการเสียหาย หยุดการประมวลผลทั้งหมด และต้องรีบูตเครื่อง หากการบูตมาจากหน่วยความจำแบบอ่านอย่างเดียว จะสร้างระบบที่ปลอดภัยและมีภารกิจเดียว
ตัวอย่างของรันไทม์ที่รวมไว้โดยตรงดังกล่าว ได้แก่:
- ระหว่างปี พ.ศ. 2526 ถึง พ.ศ. 2527 Digital Researchได้นำเสนอแอปพลิเคชันทางธุรกิจและการศึกษาหลายรายการสำหรับ IBM PC บนฟลอปปี้ดิสก์แบบบูตได้ ซึ่งมาพร้อมกับSpeedStart CP/M-86ซึ่งเป็นเวอร์ชันย่อของ CP/M-86 เป็นสภาพแวดล้อมรันไทม์[ 6 ] [ 7 ] [ 8 ] [ 9 ] [ 10 ]
- บางเวอร์ชันแบบสแตนด์อะโลนของVentura Publisher (1986–1993) [ 11 ] Artline (1988–1991) [ 11 ] Timeworks Publisher (1988–1991) และViewMAX (1990–1992) [ 12 ] [ 13 ] [ 14 ] มีเวอร์ชันรันไทม์พิเศษของ GEMของ Digital Research เป็นสภาพแวดล้อมรันไทม์[ 11 ]
- ในช่วงปลายทศวรรษ 1990 โปรเซสเซอร์บรรทัดคำสั่ง 4DOSของJP Softwareมีให้เลือกใช้ในเวอร์ชันรันไทม์พิเศษเพื่อเชื่อมโยงกับงานแบตช์ที่คอมไพล์และเข้ารหัสไว้ล่วงหน้า ของ BATCOMPเพื่อสร้างไฟล์ปฏิบัติการ ที่ไม่สามารถแก้ไขได้ จากสคริปต์แบตช์และเรียกใช้บนระบบที่ไม่ได้ติดตั้ง 4DOS [ 15 ]
ตัวอย่าง
ระบบรันไทม์ของภาษาซีคือชุดคำสั่งเฉพาะที่คอมไพเลอร์แทรกเข้าไปในอิมเมจไฟล์ปฏิบัติการ คำสั่งเหล่านี้ทำหน้าที่หลายอย่าง เช่น จัดการสแต็กของกระบวนการ สร้างพื้นที่สำหรับตัวแปรโลคอล และคัดลอกพารามิเตอร์การเรียกฟังก์ชันไปไว้ด้านบนสุดของสแต็ก
บ่อยครั้งที่ไม่มีเกณฑ์ที่ชัดเจนในการพิจารณาว่าพฤติกรรมใดของภาษาเป็นส่วนหนึ่งของระบบรันไทม์เอง และพฤติกรรมใดที่สามารถกำหนดได้โดยโปรแกรมต้นฉบับใด ๆ ตัวอย่างเช่น ในภาษาซี การตั้งค่าสแต็กเป็นส่วนหนึ่งของระบบรันไทม์ ไม่ได้ถูกกำหนดโดยความหมายของโปรแกรมแต่ละโปรแกรม เนื่องจากพฤติกรรมนี้ไม่เปลี่ยนแปลงในระดับสากล กล่าวคือ มันคงอยู่ในการทำงานทุกครั้ง พฤติกรรมที่เป็นระบบนี้เป็นการนำแบบจำลองการทำงานของภาษามาใช้ ไม่ใช่การนำความหมายของโปรแกรมเฉพาะมาใช้ (ซึ่งข้อความจะถูกแปลงเป็นโค้ดที่คำนวณผลลัพธ์โดยตรง)
การแยกส่วนระหว่างความหมายของโปรแกรมเฉพาะกับสภาพแวดล้อมการทำงานสะท้อนให้เห็นได้จากวิธีการคอมไพล์โปรแกรมที่แตกต่างกัน: การคอมไพล์ซอร์สโค้ดเป็นไฟล์ออบเจ็กต์ที่มีฟังก์ชันทั้งหมด กับการคอมไพล์โปรแกรมทั้งหมดเป็นไฟล์ไบนารีที่สามารถเรียกใช้งานได้ ไฟล์ออบเจ็กต์จะมีเฉพาะโค้ดแอสเซมบลีที่เกี่ยวข้องกับฟังก์ชันที่รวมอยู่ ในขณะที่ไฟล์ไบนารีที่สามารถเรียกใช้งานได้จะมีโค้ดเพิ่มเติมที่ใช้ในการสร้างสภาพแวดล้อมการทำงาน ไฟล์ออบเจ็กต์อาจขาดข้อมูลจากสภาพแวดล้อมการทำงาน ซึ่งจะได้รับการแก้ไขโดยการเชื่อมโยงในอีกด้านหนึ่ง โค้ดในไฟล์ออบเจ็กต์ยังคงขึ้นอยู่กับข้อสมมติในระบบการทำงาน ตัวอย่างเช่น ฟังก์ชันอาจอ่านพารามิเตอร์จากรีจิสเตอร์หรือตำแหน่งสแต็กเฉพาะ ขึ้นอยู่กับข้อกำหนดการเรียกใช้ที่ใช้โดยสภาพแวดล้อมการทำงาน
อีกตัวอย่างหนึ่งคือกรณีของการใช้Application Programming Interface (API) เพื่อโต้ตอบกับระบบรันไทม์ การเรียกใช้ API นั้นดูเหมือนกับการเรียกใช้ไลบรารีซอฟต์แวร์ ทั่วไป แต่ในบางจุดระหว่างการเรียกใช้ รูปแบบการทำงานจะเปลี่ยนไป ระบบรันไทม์ใช้รูปแบบการทำงานที่แตกต่างจากภาษาที่ใช้เขียนไลบรารีนั้น ผู้ที่อ่านโค้ดของไลบรารีทั่วไปจะสามารถเข้าใจพฤติกรรมของไลบรารีได้โดยรู้เพียงแค่ภาษาที่ใช้เขียนไลบรารีนั้น แต่ผู้ที่อ่านโค้ดของ API ที่เรียกใช้ระบบรันไทม์จะไม่สามารถเข้าใจพฤติกรรมของการเรียกใช้ API ได้เพียงแค่รู้ภาษาที่ใช้เขียนการเรียกใช้นั้น ในบางจุด ผ่านกลไกบางอย่าง รูปแบบการทำงานจะหยุดเป็นรูปแบบการทำงานของภาษาที่ใช้เขียนการเรียกใช้ และเปลี่ยนไปเป็นรูปแบบการทำงานที่ระบบรันไทม์ใช้ ตัวอย่างเช่น คำสั่ง trap เป็นหนึ่งในวิธีการเปลี่ยนรูปแบบการทำงาน ความแตกต่างนี้เองที่ทำให้รูปแบบการทำงานที่เรียกใช้ผ่าน API เช่น Pthreads แตกต่างจากไลบรารีซอฟต์แวร์ทั่วไป ทั้งการเรียกใช้ Pthreads และการเรียกใช้ไลบรารีซอฟต์แวร์นั้นเกิดขึ้นผ่าน API แต่พฤติกรรมของ Pthreads ไม่สามารถเข้าใจได้จากภาษาของการเรียกใช้ แต่การเรียกใช้ Pthreads จะนำเอาโมเดลการทำงานภายนอกเข้ามาใช้ ซึ่งถูกนำไปใช้โดยระบบรันไทม์ของ Pthreads (ระบบรันไทม์นี้มักจะเป็นเคอร์เนลของระบบปฏิบัติการ)
ตัวอย่างสุดขั้วอย่างหนึ่งคือ ซีพียูทางกายภาพเองอาจถูกมองว่าเป็นการนำระบบรันไทม์ของภาษาแอสเซมบลีเฉพาะมาใช้ ในมุมมองนี้ โมเดลการประมวลผลถูกนำไปใช้โดยซีพียูทางกายภาพและระบบหน่วยความจำ ในทำนองเดียวกัน ระบบรันไทม์สำหรับภาษาโปรแกรมระดับสูงก็ถูกนำไปใช้โดยใช้ภาษาอื่นๆ สิ่งนี้สร้างลำดับชั้นของระบบรันไทม์ โดยที่ซีพียูเอง หรือจริงๆ แล้วตรรกะของมันใน ระดับ ไมโครโค้ดหรือต่ำกว่านั้น ทำหน้าที่เป็นระบบรันไทม์ระดับต่ำสุด
คุณสมบัติขั้นสูง
ภาษาโปรแกรมแบบคอมไพล์หรือแบบอินเตอร์พรีเตอร์บางภาษาจะมีอินเทอร์เฟซที่อนุญาตให้โค้ดแอปพลิเคชันโต้ตอบกับระบบรันไทม์ได้โดยตรง ตัวอย่างเช่นThreadคลาส `const` ในภาษา Javaคลาสนี้อนุญาตให้โค้ด (ที่ทำงานโดยเธรดเดียว) ทำสิ่งต่างๆ เช่น เริ่มและหยุดเธรดอื่นๆ ได้ โดยปกติแล้ว คุณสมบัติหลักของพฤติกรรมของภาษา เช่นการจัดตารางงานและการจัดการทรัพยากรจะไม่สามารถเข้าถึงได้ด้วยวิธีนี้
พฤติกรรมระดับสูงที่ระบบรันไทม์ใช้งานอาจรวมถึงงานต่างๆ เช่น การวาดข้อความบนหน้าจอหรือการเชื่อมต่ออินเทอร์เน็ต บ่อยครั้งที่ระบบปฏิบัติการก็มีพฤติกรรมเหล่านี้เช่นกัน และเมื่อมี ระบบรันไทม์จะถูกนำมาใช้เป็นเลเยอร์นามธรรมที่แปลงการเรียกใช้ระบบรันไทม์เป็นการเรียกใช้ระบบปฏิบัติการ ซึ่งจะซ่อนความซับซ้อนหรือความแตกต่างในบริการที่ระบบปฏิบัติการต่างๆ นำเสนอ นอกจากนี้ยังหมายความว่าเคอร์เนลของระบบปฏิบัติการเองก็สามารถมองได้ว่าเป็นระบบรันไทม์ และชุดของการเรียกใช้ระบบปฏิบัติการที่เรียกใช้พฤติกรรมของระบบปฏิบัติการอาจถูกมองว่าเป็นการโต้ตอบกับระบบรันไทม์
โดยขีดจำกัดแล้ว ระบบรันไทม์อาจให้บริการต่างๆ เช่นเครื่อง P-codeหรือเครื่องเสมือน ซึ่งซ่อนแม้กระทั่ง ชุดคำสั่งของโปรเซสเซอร์นี่คือแนวทางที่ใช้ในภาษาโปรแกรมแบบตีความ หลายภาษา เช่นAWKและบางภาษา เช่นJavaซึ่งถูกออกแบบมาให้คอมไพล์เป็น รหัส ตัวแทนระดับกลาง ที่ไม่ขึ้นกับเครื่อง (เช่นไบต์โค้ด ) การจัดเรียงแบบนี้ช่วยลดความซับซ้อนของงานการใช้งานภาษาและการปรับให้เข้ากับเครื่องต่างๆ และเพิ่มประสิทธิภาพของฟีเจอร์ภาษาที่ซับซ้อน เช่นการเขียนโปรแกรมแบบสะท้อน (reflective programming) นอกจากนี้ ยังช่วยให้สามารถเรียกใช้โปรแกรมเดียวกันบนเครื่องใดก็ได้โดยไม่ต้องคอมไพล์ใหม่โดยชัดเจน ซึ่งเป็นคุณสมบัติที่สำคัญมากนับตั้งแต่การแพร่หลายของเวิลด์ไวด์เว็บเพื่อเพิ่มความเร็วในการทำงาน ระบบรันไทม์บางระบบจึงมีฟีเจอร์ การคอมไพล์ แบบทันเวลา (just-in-time compilation)ไปเป็นรหัสเครื่อง
ลักษณะเด่นอย่างหนึ่งของระบบรันไทม์สมัยใหม่คือพฤติกรรมการประมวลผลแบบขนาน เช่น พฤติกรรมที่แสดงโดยโครงสร้างมิวเท็กซ์ในPthreadsและโครงสร้างส่วนขนานในOpenMPระบบรันไทม์ที่มีพฤติกรรมการประมวลผลแบบขนานดังกล่าวสามารถแบ่งเป็นโมดูลได้ตามแนวทางโปรโตรันไทม์
ประวัติศาสตร์
ตัวอย่างที่โดดเด่นของระบบรันไทม์ในยุคแรกๆ ได้แก่ ตัวแปลภาษาBASICและLispสภาพแวดล้อมเหล่านี้ยังรวมถึงตัวเก็บขยะ (garbage collector ) ด้วย Forthเป็นตัวอย่างแรกๆ ของภาษาที่ออกแบบมาเพื่อคอมไพล์เป็นรหัสตัวแทนระดับกลาง (intermediate representation code) ระบบรันไทม์ของมันคือเครื่องเสมือน (virtual machine) ที่ตีความรหัสนั้น อีกตัวอย่างหนึ่งที่เป็นที่นิยม แม้จะเป็นเพียงทฤษฎี ก็คือคอมพิวเตอร์ MIXของDonald Knuth
ใน ภาษา ซีและภาษาอื่นๆ ที่รองรับการจัดสรรหน่วยความจำแบบไดนามิก ระบบรันไทม์ยังรวมถึงไลบรารีที่จัดการพูลหน่วยความจำของโปรแกรมด้วย
ในภาษาการเขียนโปรแกรมเชิงวัตถุระบบรันไทม์มักมีหน้าที่รับผิดชอบในการตรวจสอบประเภทแบบไดนามิกและการแก้ไขการอ้างอิงเมธอดด้วยเช่นกัน
ดูเพิ่มเติม
- แบบจำลองการดำเนินการ
- แบบจำลองการเขียนโปรแกรม
- รันไทม์ (ระยะของวงจรชีวิตโปรแกรม)
- บูตเองได้
- การสร้างแบบคงที่
อ่านเพิ่มเติม
- "NAME ENTX - Microsoft MS-DOS Computer Pascal runtime system control" . 1.00. Microsoft Corp . 1981 . สืบค้นเมื่อ2018-09-23 .
{{cite web}}: CS1 maint: บริการเก็บถาวรที่เลิกใช้แล้ว ( ลิงก์ )
ลิงก์ภายนอก
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ ระบบรันไทม์
ใน การเขียนโปรแกรมคอมพิวเตอร์ ระบบ รันไทม์ หรือเรียกสั้นๆ ว่า รันไทม์ คือระบบย่อยที่มีอยู่ในคอมพิวเตอร์ที่สร้างโปรแกรม รวมถึงในคอมพิวเตอร์ที่ตั้งใจจะรันโปรแกรม ชื่อนี้มาจากการ...
ภาพรวม
ทุกภาษาโปรแกรมกำหนด รูปแบบการทำงาน และหลายภาษาใช้ระบบรันไทม์อย่างน้อยบางส่วนในการนำรูปแบบนั้นไปใช้ หนึ่งในนิยามที่เป็นไปได้ของพฤติกรรมระบบรันไทม์คือ "พฤติกรรมใดๆ ที่ไม่ได้เกิดจากโปรแกรมโดยตรง" นิยามนี้รวมถึงการวางพารามิเตอร์ลงบนสแต็กก่อนเรียกฟังก์ชัน...
ความสัมพันธ์กับสภาพแวดล้อมขณะทำงาน
ระบบรันไทม์เป็นเสมือนประตูที่โปรแกรมที่กำลังทำงานอยู่ใช้ในการโต้ตอบกับ สภาพแวดล้อมรันไทม์ สภาพแวดล้อมรันไทม์ไม่เพียงแต่รวมถึงค่าสถานะที่เข้าถึงได้เท่านั้น แต่ยังรวมถึงเอนทิตีที่ทำงานได้ซึ่งโปรแกรมสามารถโต้ตอบด้วยในระหว่างการทำงาน ตัวอย่างเช่น...
ตัวอย่าง
ระบบรันไทม์ของ ภาษาซี คือชุดคำสั่งเฉพาะที่คอมไพเลอร์แทรกเข้าไปในอิมเมจไฟล์ปฏิบัติการ คำสั่งเหล่านี้ทำหน้าที่หลายอย่าง เช่น จัดการสแต็กของกระบวนการ สร้างพื้นที่สำหรับตัวแปรโลคอล และคัดลอกพารามิเตอร์การเรียกฟังก์ชันไปไว้ด้านบนสุดของสแต็ก