Chyba sběrnice - Bus error

Ve výpočtu , je chyba sběrnice je závada zvýšen hardwarem, oznámí je operační systém (OS), že proces se pokouší získat přístup k paměti , že CPU nemůže fyzicky adresa: neplatná adresa pro adresovou sběrnici , proto jméno. V moderním použití na většině architektur se jedná o mnohem vzácnější chyby segmentace , ke kterým dochází primárně kvůli narušení přístupu k paměti: problémům s logickou adresou nebo oprávněními.

Na platformách vyhovujících POSIX mají chyby sběrnice obvykle za následek odeslání signálu SIGBUS do procesu, který chybu způsobil. SIGBUS může být také způsobena tím, jakékoliv obecné poruše zařízení, která počítač zjistí, když chyba sběrnice zřídka znamená, že hardware počítače je fyzicky zlomený je obvykle způsobena chybou v softwaru . Chyby sběrnice mohou být také vyvolány pro některé další chyby stránkování; viz. níže.

Příčiny

Existují nejméně tři hlavní příčiny chyb sběrnice:

Neexistující adresa

Software dává CPU pokyn, aby četl nebo zapisoval konkrétní adresu fyzické paměti . Podle toho CPU nastaví tuto fyzickou adresu na svou adresovou sběrnici a požaduje, aby veškerý další hardware připojený k CPU odpověděl s výsledky, pokud odpoví na tuto konkrétní adresu. Pokud žádný jiný hardware neodpoví, CPU vyvolá výjimku a uvede, že požadovaná fyzická adresa není rozpoznána celým počítačovým systémem. Toto se vztahuje pouze na adresy fyzické paměti. Pokus o přístup k nedefinované adrese virtuální paměti je obecně považován za chybu segmentace, spíše než za chybu sběrnice, i když je-li MMU samostatná, procesor nemůže poznat rozdíl.

Nezaručený přístup

Většina procesorů je adresovatelná bajty , přičemž každá jedinečná adresa paměti odkazuje na 8bitový bajt . Většina procesorů může přistupovat k jednotlivým bajtům z každé adresy paměti, ale obecně nemají přístup k větším jednotkám (16 bitů, 32 bitů, 64 bitů atd.), Aniž by tyto jednotky byly „ zarovnány “ na konkrétní hranici ( platforma x86 je významnou výjimkou ).

Například pokud musí být vícebajtové přístupy zarovnány na 16 bitů, adresy (zadané v bajtech) na 0, 2, 4, 6 atd. By byly považovány za zarovnané a proto přístupné, zatímco adresy 1, 3, 5 a tak dále by bylo považováno za nevyrovnané. Podobně, pokud musí být vícebajtové přístupy zarovnány na 32 bitů, adresy 0, 4, 8, 12 atd. By byly považovány za zarovnané a proto přístupné a všechny adresy mezi nimi by byly považovány za nevyrovnané. Pokus o přístup k jednotce větší než bajt na nezařazené adrese může způsobit chybu sběrnice.

Některé systémy mohou mít hybridní z nich v závislosti na použité architektuře. Například pro hardware založený na sálovém počítači IBM System / 360 , včetně IBM System z , Fujitsu B8000, RCA Spectra a UNIVAC Series 90 , musí být pokyny na 16bitové hranici, tj. Adresy spuštění musí začínat na sudý bajt. Pokusy o větvení na lichou adresu způsobí výjimku specifikace. Data však mohou být načtena z jakékoli adresy v paměti a mohou být jeden bajt nebo delší v závislosti na instrukci.

CPU obecně přistupují k datům v plné šířce své datové sběrnice vždy. Chcete-li adresovat bajty, přistupují k paměti na celou šířku své datové sběrnice, poté maskují a posouvají adresování jednotlivých bajtů. Systémy tolerují tento neefektivní algoritmus, protože je to základní funkce většiny softwaru, zejména zpracování řetězců . Na rozdíl od bajtů mohou větší jednotky zahrnovat dvě zarovnané adresy a vyžadovaly by tedy více než jedno načtení na datové sběrnici. Je možné, že to CPU podporují, ale tato funkce je zřídka vyžadována přímo na úrovni strojového kódu , takže návrháři CPU se ji obvykle vyhnou implementaci a místo toho vydají chyby sběrnice pro nevyrovnaný přístup do paměti.

Chyby stránkování

FreeBSD , Linux a Solaris mohou signalizovat chybu sběrnice, když nelze stránkovat stránky virtuální paměti , např. Protože zmizel (např. Přístup k souboru mapovanému do paměti nebo spuštění binárního obrazu, který byl během běhu programu zkrácen), nebo proto, že právě vytvořený soubor mapovaný do paměti nelze fyzicky přidělit, protože disk je plný.

Nepřítomný segment (x86)

Na x86 existuje starší mechanismus správy paměti známý jako segmentace . Pokud aplikace načte segmentový registr selektorem nepřítomného segmentu (který lze v operačních systémech kompatibilních s POSIX provést pouze s jazykem sestavení ), vygeneruje se výjimka. Některé operační systémy to používaly pro výměnu, ale pod Linuxem to generuje SIGBUS.

Příklad

Toto je příklad nezarovnaného přístupu do paměti, napsaný v programovacím jazyce C se syntaxí sestavení AT&T .

#include <stdlib.h>

int main(int argc, char **argv) 
{
    int *iptr;
    char *cptr;
    
#if defined(__GNUC__)
# if defined(__i386__)
    /* Enable Alignment Checking on x86 */
    __asm__("pushf\norl $0x40000,(%esp)\npopf");
# elif defined(__x86_64__) 
     /* Enable Alignment Checking on x86_64 */
    __asm__("pushf\norl $0x40000,(%rsp)\npopf");
# endif
#endif

    /* malloc() always provides aligned memory */
    cptr = malloc(sizeof(int) + 1);
    
    /* Increment the pointer by one, making it misaligned */
    iptr = (int *) ++cptr;

    /* Dereference it as an int pointer, causing an unaligned access */
    *iptr = 42;

    /*
       Following accesses will also result in sigbus error.
       short *sptr;
       int    i;

       sptr = (short *)&i;
       // For all odd value increments, it will result in sigbus.
       sptr = (short *)(((char *)sptr) + 1);
       *sptr = 100;
    
    */

    return 0;
}

Kompilace a spuštění příkladu na OS kompatibilním s POSIX na x86 ukazuje chybu:

$ 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

Na GDB debugger ukazuje, že hodnota okamžité 0x2A je uložena na místě uložené v EAX registru pomocí X86 jazyk symbolických instrukcí . Toto je příklad nepřímého adresování registru .

Tisk bitů nižšího řádu adresy ukazuje, že není zarovnán s hranicí slova ("dword" pomocí x86 terminologie).

Reference