stringtranslate.com

Ошибка шины

В вычислениях ошибка шины — это аппаратный сбой , уведомляющий операционную систему (ОС) о том, что процесс пытается получить доступ к памяти , к которой процессор физически не может обратиться: неверный адрес для адресной шины , отсюда и название. В современном использовании на большинстве архитектур они встречаются гораздо реже, чем ошибки сегментации , которые возникают в первую очередь из-за нарушений доступа к памяти: проблем с логическим адресом или разрешениями.

На платформах, совместимых с POSIX , ошибки шины обычно приводят к отправке сигнала SIGBUS процессу, вызвавшему ошибку. SIGBUS также может быть вызван любой общей неисправностью устройства, которую обнаруживает компьютер, хотя ошибка шины редко означает, что аппаратное обеспечение компьютера физически неисправно — обычно это вызвано ошибкой в ​​программном обеспечении . [ нужна цитация ] Ошибки шины также могут возникать при некоторых других ошибках подкачки; см. ниже.

Причины

Существует как минимум три основные причины ошибок шины:

Несуществующий адрес

Программное обеспечение инструктирует ЦП читать или записывать определенный адрес физической памяти . Соответственно, ЦП устанавливает этот физический адрес на своей адресной шине и запрашивает все остальное оборудование, подключенное к ЦП, ответить результатами, если они отвечают по этому конкретному адресу. Если никакое другое оборудование не отвечает, ЦП выдает исключение , указывающее, что запрошенный физический адрес не распознается всей компьютерной системой. Обратите внимание, что это касается только адресов физической памяти. Попытка доступа к неопределенному адресу виртуальной памяти обычно считается ошибкой сегментации, а не ошибкой шины, хотя, если 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] Однако данные могут быть получены по любому адресу в памяти и могут иметь размер одного байта или больше, в зависимости от инструкции.

Процессоры обычно всегда обращаются к данным по всей ширине своей шины данных . Для адресации байтов они обращаются к памяти по всей ширине своей шины данных, затем маскируют и сдвигают адрес для обращения к отдельному байту. Системы допускают этот неэффективный алгоритм, поскольку он является важной функцией большинства программ, особенно для обработки строк . В отличие от байтов, более крупные единицы могут охватывать два выровненных адреса и, таким образом, потребуют более одной выборки по шине данных. ЦП могут поддерживать это, но эта функциональность редко требуется непосредственно на уровне машинного кода , поэтому разработчики ЦП обычно избегают ее реализации и вместо этого выдают ошибки шины для невыровненного доступа к памяти.

Ошибки подкачки

FreeBSD , Linux и Solaris могут сигнализировать об ошибке шины, когда страницы виртуальной памяти не могут быть выгружены , например, потому что она исчезла (например, доступ к файлу, отображаемому в памяти , или выполнение двоичного образа , который был усечен во время работы программы), [2] ] [ ненадежный источник? ] или потому, что только что созданный файл, отображенный в памяти, не может быть физически выделен, поскольку диск заполнен.

Отсутствующий сегмент (x86)

В x86 существует более старый механизм управления памятью, известный как сегментация . Если приложение загружает регистр сегмента с помощью селектора несуществующего сегмента (что в POSIX-совместимых ОС можно выполнить только с помощью языка ассемблера ), генерируется исключение. Некоторые операционные системы использовали это для подкачки, но в Linux это генерирует SIGBUS.

Пример

Это пример невыровненного доступа к памяти, написанный на языке программирования C с синтаксисом ассемблера AT&T .

#include <stdlib.h> int main ( int argc , char ** argv ) { int * iptr ; символ * cptr ; #if определено(__GNUC__) # если определено(__i386__) /* Включить проверку выравнивания на x86 */ __asm__ ( "pushf \n orl $0x40000,(%esp) \n popf" ); # elif определено(__x86_64__) /* Включить проверку выравнивания на x86_64 */ __asm__ ( "pushf \n orl $0x40000,(%rsp) \n popf" ); #конец #конецif               /* malloc() всегда предоставляет память, выровненную по всем фундаментальным типам */ cptr = malloc ( sizeof ( int ) + 1 ); /* Увеличиваем указатель на единицу, делая его смещенным */ iptr = ( int * ) ++ cptr ;             /* Разыменовываем его как указатель int, вызывая невыровненный доступ */ * iptr = 42 ;    /*  Последующие обращения также приведут к ошибке sigbus.  короткий *sptr;  интервал я; sptr = (коротко *)&i;  // Для всех приращений нечетных значений результатом будет sigbus.  sptr = (short *)(((char *)sptr) + 1);  *сптр = 100;  */  вернуть 0 ; } 

Компиляция и запуск примера в POSIX -совместимой ОС на x86 демонстрирует ошибку:

$ gcc  -ansi  sigbus.c  -o  sigbus $ ./sigbus Ошибка шины $ gdb ./sigbus (gdb) r Программа получила сигнал SIGBUS, ошибка шины. 0x080483ba в 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).

Рекомендации

  1. ^ z/Принципы работы архитектуры , SA22-7832-04, стр. 6-6, пятое издание (сентябрь 2005 г.) IBM Corporation, Поукипси, штат Нью-Йорк, можно получить по адресу http://publibfp.dhe.ibm.com/epubs/pdf. /a2278324.pdf Архивировано 22 мая 2022 г. в Wayback Machine (получено 31 декабря 2015 г.).
  2. ^ «Что такое SIGBUS — аппаратная ошибка конкретного объекта?».