Из Википедии, свободной энциклопедии
Перейти к навигации Перейти к поиску

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

На платформах, совместимых с 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 ;  char  * cptr ; # если  определено (__ GNUC__) # если определено (__ 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.  короткие * 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)  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 язык ассемблера . Это пример косвенной адресации регистров .

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

Ссылки [ править ]

  1. ^ z / Принципы работы архитектуры , SA22-7832-04, стр. 6-6, пятое издание (сентябрь 2005 г.) IBM Corporation, Поукипси, штат Нью-Йорк, можно получить с 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 [ ненадежный источник? ]