Ошибка шины - Bus error

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

На 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 серии 90, инструкции должны быть на 16-битной границе, то есть адреса выполнения должны начинаться с четного байта. Попытки перейти на нечетный адрес приводят к исключению спецификации.[1] Однако данные могут быть получены из любого адреса в памяти и могут быть одним байтом или больше в зависимости от инструкции.

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

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

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

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

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

Пример

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

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

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

$ gcc -ansi sigbus.c -o sigbus$ ./sigbus Ошибка шины$ gdb ./sigbus(GDB) рПрограмма получила сигнал SIGBUS, Ошибка шины.0x080483ba в main ()(GDB) x / i $ шт0x80483ba 
: mov DWORD PTR [eax], 0x2a(GDB) p / x $ eax$1 = 0x804a009(GDB) p / t $ eax & (sizeof (int) - 1)$2 = 1

В GDB отладчик показывает, что немедленная ценность 0x2a хранится в месте, хранящемся в EAX регистр, с помощью Язык ассемблера X86. Это пример регистрировать косвенный адресация.

Печать биты младшего разряда адреса показывает, что это не выровнен по границе слова («двойное слово» в терминологии x86).

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

  1. ^ z / Архитектура Принципы работы, SA22-7832-04, стр. 6-6, пятое издание (сентябрь 2005 г.) IBM Corporation, Poukeepsie, NY, можно получить из http://publibfp.dhe.ibm.com/epubs/pdf/a2278324.pdf (Проверено 31 декабря 2015 г.)
  2. ^ https://groups.google.com/group/comp.unix.internals/browse_thread/thread/6369e8f923aedcb0/54f8ed15e326dc0[ненадежный источник? ]