อ่าน 3 นาที
ข้อผิดพลาดของบัส
ในด้าน คอมพิวเตอร์ ข้อผิดพลาดของบัส (Bus error ) คือ ความผิดพลาด ที่เกิดขึ้นจากฮาร์ดแวร์ ซึ่งแจ้งให้ ระบบปฏิบัติการ (OS) ทราบว่ากระบวนการหนึ่งกำลังพยายามเข้าถึง หน่วยความจำ ที่...
ข้อผิดพลาดของบัส
ในด้านคอมพิวเตอร์ข้อผิดพลาดของบัส (Bus error ) คือความผิดพลาดที่เกิดขึ้นจากฮาร์ดแวร์ ซึ่งแจ้งให้ระบบปฏิบัติการ (OS) ทราบว่ากระบวนการหนึ่งกำลังพยายามเข้าถึงหน่วยความจำที่ซีพียูไม่สามารถเข้าถึงได้จริง กล่าวคือ เป็นที่อยู่ที่ไม่ถูกต้องสำหรับบัสที่อยู่ (address bus ) จึงเป็นที่มาของชื่อนี้ ในการใช้งานสมัยใหม่บนสถาปัตยกรรมส่วนใหญ่ ข้อผิดพลาดเหล่านี้เกิดขึ้นได้ยากกว่าข้อผิดพลาดของการแบ่งส่วนหน่วยความจำ (Segmentation fault)ซึ่งส่วนใหญ่เกิดจากการละเมิดการเข้าถึงหน่วยความจำ เช่น ปัญหาในที่อยู่เชิงตรรกะหรือสิทธิ์การเข้าถึง
บน แพลตฟอร์มที่รองรับมาตรฐาน POSIXข้อผิดพลาดของบัสโดยทั่วไปจะส่งผลให้มีการส่งสัญญาณ SIGBUS ไปยังกระบวนการที่ก่อให้เกิดข้อผิดพลาดนั้น SIGBUS อาจเกิดจากความผิดพลาดของอุปกรณ์ทั่วไปที่คอมพิวเตอร์ตรวจพบได้เช่นกัน แม้ว่าข้อผิดพลาดของบัสจะไม่ค่อยหมายความว่าฮาร์ดแวร์ของคอมพิวเตอร์เสียหายทางกายภาพก็ตาม โดยปกติแล้วมักเกิดจากข้อบกพร่องในซอฟต์แวร์นอกจากนี้ ข้อผิดพลาดของบัสอาจเกิดขึ้นจากข้อผิดพลาดในการเพจจิ้งอื่นๆ ด้วย โปรดดูรายละเอียดเพิ่มเติมด้านล่าง
สาเหตุ
สาเหตุหลักอย่างน้อยสามประการที่ทำให้เกิดข้อผิดพลาดบนบัส ได้แก่:
ที่อยู่ไม่มีอยู่จริง
ซอฟต์แวร์จะสั่งการให้ CPU อ่านหรือเขียนที่อยู่หน่วยความจำทาง กายภาพที่เฉพาะเจาะจง จากนั้น CPU จะตั้งค่าที่อยู่ทางกายภาพนี้บนบัสแอดเดรส ของมัน และร้องขอให้ฮาร์ดแวร์อื่นๆ ที่เชื่อมต่อกับ CPU ตอบกลับด้วยผลลัพธ์ หากฮาร์ดแวร์เหล่านั้นตอบสนองต่อที่อยู่เฉพาะนี้ หากไม่มีฮาร์ดแวร์อื่นใดตอบสนอง CPU จะส่งข้อผิดพลาดโดยระบุว่าที่อยู่ทางกายภาพที่ร้องขอไม่ได้รับการยอมรับจากระบบคอมพิวเตอร์ทั้งหมด โปรดทราบว่านี่ครอบคลุมเฉพาะ ที่อยู่หน่วยความจำ ทางกายภาพ เท่านั้น การพยายามเข้าถึง ที่อยู่หน่วย ความจำเสมือน ที่ไม่กำหนดไว้ โดยทั่วไปถือว่าเป็นข้อผิดพลาดในการแบ่งส่วน (segmentation fault) มากกว่าข้อผิดพลาดของบัส (bus error) แม้ว่าหากMMUแยกต่างหาก โปรเซสเซอร์จะไม่สามารถแยกแยะความแตกต่างได้
การเข้าถึงที่ไม่สอดคล้องกัน
ซีพียูส่วนใหญ่สามารถเข้าถึงได้ทีละไบต์โดยที่แต่ละที่อยู่หน่วยความจำที่ไม่ซ้ำกันจะหมายถึงไบต์ ขนาด 8 บิต ซีพียูส่วนใหญ่สามารถเข้าถึงไบต์แต่ละตัวจากที่อยู่หน่วยความจำแต่ละแห่งได้ แต่โดยทั่วไปแล้วจะไม่สามารถเข้าถึงหน่วยที่ใหญ่กว่า (16 บิต, 32 บิต, 64 บิต และอื่นๆ) ได้หากหน่วยเหล่านั้นไม่ได้ " จัดเรียง " ให้ตรงกับขอบเขตที่กำหนด ( แพลตฟอร์ม x86เป็นข้อยกเว้นที่สำคัญ)
ตัวอย่างเช่น หากการเข้าถึงข้อมูลหลายไบต์ต้องมีการจัดเรียงแบบ 16 บิต ที่อยู่ (ที่ระบุเป็นไบต์) ที่ 0, 2, 4, 6 และอื่นๆ จะถือว่ามีการจัดเรียงและสามารถเข้าถึงได้ ในขณะที่ที่อยู่ 1, 3, 5 และอื่นๆ จะถือว่าไม่มีการจัดเรียง ในทำนองเดียวกัน หากการเข้าถึงข้อมูลหลายไบต์ต้องมีการจัดเรียงแบบ 32 บิต ที่อยู่ 0, 4, 8, 12 และอื่นๆ จะถือว่ามีการจัดเรียงและสามารถเข้าถึงได้ และที่อยู่ทั้งหมดที่อยู่ระหว่างนั้นจะถือว่าไม่มีการจัดเรียง การพยายามเข้าถึงหน่วยที่มีขนาดใหญ่กว่าหนึ่งไบต์ที่ที่อยู่ที่ไม่มีการจัดเรียงอาจทำให้เกิดข้อผิดพลาดของบัสได้
บางระบบอาจมีการผสมผสานระหว่างสิ่งเหล่านี้ ขึ้นอยู่กับสถาปัตยกรรมที่ใช้ ตัวอย่างเช่น สำหรับฮาร์ดแวร์ที่ใช้ เมนเฟรม IBM System/360รวมถึงIBM System z , Fujitsu B8000, RCA Spectra และUNIVAC Series 90คำสั่งจะต้องอยู่บนขอบเขต 16 บิต นั่นคือ ที่อยู่การดำเนินการจะต้องเริ่มต้นที่ไบต์คู่ การพยายามแยกไปยังที่อยู่คี่จะส่งผลให้เกิดข้อยกเว้นตามข้อกำหนด[ 1 ]อย่างไรก็ตาม ข้อมูลอาจถูกดึงมาจากที่อยู่ใดก็ได้ในหน่วยความจำ และอาจมีหนึ่งไบต์หรือมากกว่านั้น ขึ้นอยู่กับคำสั่ง
โดยทั่วไปแล้ว CPU จะเข้าถึงข้อมูลที่ความกว้างเต็มของบัสข้อมูลตลอดเวลา ในการเข้าถึงไบต์ CPU จะเข้าถึงหน่วยความจำที่ความกว้างเต็มของบัสข้อมูล จากนั้นจึงทำการมาสก์และเลื่อนเพื่อเข้าถึงไบต์แต่ละตัว ระบบยอมรับอัลกอริทึมที่ไม่ประสิทธิภาพนี้ได้ เนื่องจากเป็นคุณสมบัติที่จำเป็นสำหรับซอฟต์แวร์ส่วนใหญ่ โดยเฉพาะอย่างยิ่ง การประมวลผล สตริงต่างจากไบต์ หน่วยที่ใหญ่กว่าสามารถครอบคลุมที่อยู่สองตำแหน่งที่จัดเรียงกันได้ ดังนั้นจึงต้องใช้การดึงข้อมูลบนบัสมากกว่าหนึ่งครั้ง CPU สามารถรองรับฟังก์ชันนี้ได้ แต่ฟังก์ชันนี้ไม่ค่อยจำเป็นโดยตรงใน ระดับ รหัสเครื่องดังนั้นนักออกแบบ CPU จึงมักหลีกเลี่ยงการใช้งานและออกข้อผิดพลาดของบัสสำหรับการเข้าถึงหน่วยความจำที่ไม่จัดเรียงกันแทน
ข้อผิดพลาดในการเพจ
FreeBSD , LinuxและSolarisสามารถส่งสัญญาณข้อผิดพลาดของบัสเมื่อไม่สามารถเรียกเพจหน่วยความจำเสมือนเข้ามาได้เช่น เนื่องจากเพจนั้นหายไป (เช่น การเข้าถึงไฟล์ที่แมปหน่วยความจำหรือการเรียกใช้ภาพไบนารีที่ถูกตัดทอนในขณะที่โปรแกรมกำลังทำงาน) [ 2 ] หรือเนื่องจาก ไฟล์ที่แมปหน่วยความจำที่เพิ่งสร้างขึ้นไม่สามารถจัดสรรทางกายภาพได้ เนื่องจากดิสก์เต็ม
เซ็กเมนต์ที่ไม่มีอยู่ (x86)
บนสถาปัตยกรรม x86มีกลไกการจัดการหน่วยความจำแบบเก่าที่เรียกว่าการแบ่งส่วน (segmentation ) หากแอปพลิเคชันโหลดรีจิสเตอร์ส่วน (segment register) ด้วยตัวเลือกของส่วนที่ไม่มีอยู่จริง (ซึ่งในระบบปฏิบัติการที่รองรับ POSIX สามารถทำได้ด้วยภาษาแอสเซมบลี เท่านั้น ) จะเกิดข้อยกเว้นขึ้น ระบบปฏิบัติการบางระบบใช้กลไกนี้สำหรับการสลับข้อมูล แต่ใน Linux จะสร้างสัญญาณ SIGBUS ขึ้นมาแทน
ตัวอย่าง
นี่คือตัวอย่างของการเข้าถึงหน่วยความจำที่ไม่ตรงแนว ซึ่งเขียนด้วยภาษาโปรแกรม Cโดยใช้ ไวยากรณ์แอสเซมบลี ของ AT&T
#include <stdlib.h>int main ( int argc , char ** argv ) { int * iptr ; char * cptr ; #if defined(__GNUC__) # if defined(__i386__) /* เปิดใช้งานการตรวจสอบการจัดเรียงบน x86 */ __asm__ ( "pushf \n orl $0x40000,(%esp) \n popf" ); # elif defined(__x86_64__) /* เปิดใช้งานการตรวจสอบการจัดเรียงบน x86_64 */ __asm__ ( "pushf \n orl $0x40000,(%rsp) \n popf" ); # endif #endif/* malloc() จะจัดสรรหน่วยความจำที่จัดเรียงอย่างถูกต้องสำหรับชนิดข้อมูลพื้นฐานทั้งหมดเสมอ */ cptr = malloc ( sizeof ( int ) + 1 ); /* เพิ่มค่าตัวชี้ขึ้นหนึ่ง ทำให้ไม่จัดเรียงอย่างถูกต้อง */ iptr = ( int * ) ++ cptr ;/* เข้าถึงค่าที่ชี้โดยตัวชี้ int ซึ่งทำให้เกิดการเข้าถึงที่ไม่ตรงแนว */ * iptr = 42 ;/* การเข้าถึงต่อไปนี้จะส่งผลให้เกิดข้อผิดพลาด sigbus ด้วยเช่นกัน short *sptr; int i; sptr = (short *)&i; // สำหรับการเพิ่มค่าคี่ทั้งหมด จะได้ผลลัพธ์เป็น sigbus sptr = (short *)(((char *)sptr) + 1); *sptr = 100; */ส่งคืนค่า0 ; }การคอมไพล์และรันตัวอย่างบน ระบบปฏิบัติการที่รองรับ POSIXบนสถาปัตยกรรมx86แสดงให้เห็นข้อผิดพลาดดังนี้:
$ gcc -ansi sigbus.c -o sigbus $ ./sigbus Bus error $ gdb ./sigbus (gdb) r Program received signal SIGBUS, Bus error. 0x080483ba in main () (gdb) x/i $pc 0x80483ba <main+54>: mov DWORD PTR [eax],0x2a (gdb) p/x $eax $ 1 = 0x804a009 (gdb) p/t $eax & (sizeof(int) - 1) $ 2 = 1โปรแกรมดีบักเกอร์GDB แสดงให้เห็นว่าค่าคงที่ 0x2a ถูกจัดเก็บไว้ที่ตำแหน่งที่เก็บไว้ในรีจิสเตอร์EAXโดยใช้ภาษาแอสเซมบลี X86นี่เป็นตัวอย่างของการกำหนดแอดเดรส แบบอ้างอิงรีจิสเตอร์ทางอ้อม
การพิมพ์บิตลำดับต่ำของแอดเดรสแสดงให้เห็นว่าแอดเดรสนั้นไม่ได้จัดเรียงให้ตรงกับขอบเขตของเวิร์ด ("dword" ตามศัพท์เฉพาะของสถาปัตยกรรม x86)
สรุปเนื้อหา
ข้อมูลสำคัญจากบทความ
ข้อมูลสำคัญเกี่ยวกับ ข้อผิดพลาดของบัส
ในด้าน คอมพิวเตอร์ ข้อผิดพลาดของบัส (Bus error ) คือ ความผิดพลาด ที่เกิดขึ้นจากฮาร์ดแวร์ ซึ่งแจ้งให้ ระบบปฏิบัติการ (OS) ทราบว่ากระบวนการหนึ่งกำลังพยายามเข้าถึง หน่วยความจำ ที่...
สาเหตุ
สาเหตุหลักอย่างน้อยสามประการที่ทำให้เกิดข้อผิดพลาดบนบัส ได้แก่:
ที่อยู่ไม่มีอยู่จริง
ซอฟต์แวร์จะสั่งการให้ CPU อ่านหรือเขียน ที่อยู่หน่วยความจำทาง กายภาพที่เฉพาะเจาะจง จากนั้น CPU จะตั้งค่าที่อยู่ทางกายภาพนี้บน บัสแอดเดรส ของมัน และร้องขอให้ฮาร์ดแวร์อื่นๆ ที่เชื่อมต่อกับ CPU ตอบกลับด้วยผลลัพธ์ หากฮาร์ดแวร์เหล่านั้นตอบสนองต่อที่อยู่เฉพาะนี้...
การเข้าถึงที่ไม่สอดคล้องกัน
ซีพียูส่วนใหญ่สามารถ เข้าถึงได้ทีละไบต์ โดยที่แต่ละที่อยู่หน่วยความจำที่ไม่ซ้ำกันจะหมายถึง ไบต์ ขนาด 8 บิต ซีพียูส่วนใหญ่สามารถเข้าถึงไบต์แต่ละตัวจากที่อยู่หน่วยความจำแต่ละแห่งได้ แต่โดยทั่วไปแล้วจะไม่สามารถเข้าถึงหน่วยที่ใหญ่กว่า (16 บิต, 32 บิต, 64 บิต...