Busfehler

Im Computer, a Busfehler ist ein Fehler durch Hardware erhoben, eine Benachrichtigung eines Betriebssystem (Betriebssystem), dass ein Prozess versucht, zugreifen zu können Erinnerung dass die Zentralprozessor kann physisch nicht adressieren: eine ungültige Adresse für die Adressbus, daher der Name. In der modernen Verwendung bei den meisten Architekturen sind diese viel seltener als Segmentierungsfehler, die vor allem aufgrund von Verstößen gegen den Speicherzugriff auftreten: Probleme in der logisch die Anschrift oder Berechtigungen.

An Posix-Compliant -Bahnsachen führen Busfehler normalerweise dazu, dass das Sigbus -Signal an den Prozess gesendet wird, der den Fehler verursacht hat. Sigbus kann auch durch jeden allgemeinen Gerätefehler verursacht werden, den der Computer erkennt, obwohl ein Busfehler selten bedeutet, dass die Computerhardware ist physisch kaputt - es wird normalerweise durch a verursacht Insekt in Software. Busfehler können auch für bestimmte andere Paging -Fehler angesprochen werden. siehe unten.

Ursachen

Es gibt mindestens drei Hauptursachen für Busfehler:

Nicht existierende Adresse

Die Software weist die CPU an, ein bestimmtes physisches Lesen zu lesen oder zu schreiben Speicheradresse. Dementsprechend setzt die CPU diese physische Adresse auf ihre Adressbus und fordert alle anderen Hardware an, die mit der CPU verbunden sind, um mit den Ergebnissen zu antworten, wenn sie für diese spezielle Adresse antworten. Wenn keine andere Hardware antwortet, erhöht die CPU eine Ausnahmemit der Angabe, dass die angeforderte physische Adresse vom gesamten Computersystem nicht erkannt wird. Beachten Sie, dass dies nur abdeckt physisch Speicheradressen. Versuch, auf einen undefinierten Zugang zu geben virtueller Speicher Die Adresse wird im Allgemeinen eher als Segmentierungsfehler als als Busfehler angesehen, wenn die MMU ist getrennt, der Prozessor kann den Unterschied nicht erkennen.

Nicht ausgerichteter Zugang

Die meisten CPUs sind Byteadressibel, wo sich jede einzelne Speicheradresse auf einen 8-Bit bezieht Byte. Die meisten CPUs können von jeder Speicheradresse auf einzelne Bytes zugreifen, aber im Allgemeinen können sie im Allgemeinen nicht auf größere Einheiten (16 Bit, 32 Bit, 64 Bit usw.) zugreifen, ohne dass diese Einheiten sind. "ausgerichtet"an eine bestimmte Grenze (die x86 Plattform eine bemerkenswerte Ausnahme sein).

Wenn beispielsweise Multi-Byte-Zugriffe 16 bitgerichtet werden müssen, werden Adressen (in Bytes angegeben) bei 0, 2, 4, 6 usw. als ausgerichtet und daher zugänglich angesehen, während die Adressen 1, 3, 5 und die Ansprachen 1, 3, und zugänglich sind so weiter gilt als nicht ausgerichtet. In ähnlicher Weise müssen Multi-Byte-Zugriffe 32-Bit ausgerichtet sein, die Adressen 0, 4, 8, 12 usw. als ausgerichtet und daher zugänglich angesehen werden, und alle Adressen dazwischen würden sie als nicht ausgerichtet angesehen. Der Versuch, auf eine Einheit zuzugreifen, die größer als ein Byte an einer nicht ausgerichteten Adresse ist, kann einen Busfehler verursachen.

Einige Systeme können je nach der Verwendung der Architektur eine Mischung davon haben. Zum Beispiel für Hardware basierend auf der IBM System/360 Mainframe, einschließlich der IBM System z, Fujitsu B8000, RCA -Spektren und UNIVAC -Serie 90Anweisungen müssen an einer 16-Bit-Grenze liegen, dh Ausführungsadressen müssen auf einem gleichmäßigen Byte beginnen. Versuche, sich in eine ungerade Adresse zu verzweigen, führt zu einer Spezifikationsausnahme.[1] Daten können jedoch aus einer beliebigen Adresse im Speicher abgerufen werden und können je nach Anweisung ein Byte oder länger sein.

CPUs zugreifen im Allgemeinen auf Daten in der vollen Breite ihrer Datenbus jederzeit. Um Bytes zu adressieren, greifen sie in der vollen Breite ihres Datenbusses auf Speicher zu, maskieren und verschieben dann das einzelne Byte. Systeme tolerieren diesen ineffizienten Algorithmus, da er insbesondere für die meisten Software eine wesentliche Funktion ist Saite wird bearbeitet. Im Gegensatz zu Bytes können größere Einheiten zwei ausgerichtete Adressen umfassen und müssten daher mehr als einen Fetch im Datenbus benötigen. Es ist CPUs möglich, dies zu unterstützen, aber diese Funktionalität ist selten direkt in der Maschinensprache Niveau, so vermeiden CPU -Designer normalerweise die Implementierung und geben stattdessen Busfehler für den nicht ausgerichteten Speicherzugriff aus.

Paging -Fehler

Freebsd, Linux und Solaris kann einen Busfehler signalisieren, wenn virtuelle Speicherseiten nicht sein können in, z.B. weil es verschwunden ist (z. B. Zugriff auf a Speicher-abgebildete Datei oder ausführen a Binärbild was während des Programms abgeschnitten wurde),[2][unzuverlässige Quelle?] oder weil ein gerade geschaffener Speicher-abgebildete Datei kann nicht physisch zugewiesen werden, da die Festplatte voll ist.

Nicht-present-Segment (x86)

An x86 existiert ein älterer Speicherverwaltungsmechanismus, der als bekannt ist Segmentierung. Wenn das Anwendungssegment Segment lädt, registrieren Sie sich mit dem Selektor des nicht-present-Segment Montagesprache), die Ausnahme wird generiert. Einige Osen verwendeten das zum Austausch, aber unter Linux erzeugt dies Sigbus.

Beispiel

Dies ist ein Beispiel für einen nicht ausgerichteten Speicherzugriff, der in der geschrieben wurde C Programmiersprache mit AT & T -Assembly -Syntax.

#enthalten  int hauptsächlich(int argc, verkohlen **argv)  {   int *IPTR;   verkohlen *CPTR;    #if definiert (__ gnuc__) # wenn definiert (__ i386__)   / * Aktivieren Sie die Ausrichtungsprüfung auf x86 */   __asm__("Pushf\norl $ 0x40000, (%ESP)\nPOPF "); # Elif definiert (__ x86_64__)    / * Aktivieren Sie die Ausrichtungsprüfung auf x86_64 */   __asm__("Pushf\norl $ 0x40000, (%RSP)\nPOPF "); # endif #endif   / * malloc () liefert immer Speicher, das für alle grundlegenden Typen ausgerichtet ist */   CPTR = Malloc(Größe von(int) + 1);      / * Inkrementieren Sie den Zeiger um einen und machen ihn falsch ausgerichtet */   IPTR = (int *) ++CPTR;   / * Dereferenz als Int -Zeiger, der einen nicht ausgerichteten Zugriff verursacht */   *IPTR = 42;   /*        Der folgende Zugriff führt auch zu einem Sigbus -Fehler.        kurz *SPTR;        int i;        sptr = (kurz *) & i;        // Für alle ungeraden Wertschritte führt dies zu Sigbus.        sptr = (kurz *) (((char *) sptr) + 1);        *SPTR = 100;        */   Rückkehr 0; } 

Kompilieren und Ausführen des Beispiels auf a Posix konformes Betriebssystem auf x86 Demonstriert den Fehler:

$ GCC -ANSI SIGBUS.C -O SIGBUS$ ./sigbusBusfehler $ gdb ./sigbus(GDB) r Programm erhalten Signal Sigbus, Busfehler. 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 

Das GDB Debugger zeigt, dass die unmittelbarer Wert 0x2a wird an dem Ort gelagert, der in der gelagert wird Eax registrieren, verwenden X86 Assemblersprache. Dies ist ein Beispiel für indirekt registrieren Adressierung.

Drucken der Bit mit geringer Ordnung der Adresse zeigt, dass dies nicht der Fall ist auf eine Wortgrenze ausgerichtet ("DWORD" mit X86 -Terminologie).

Verweise

  1. ^ Z/Architekturprinzipien des Betriebs, SA22-7832-04, Seite 6-6, fünfte Ausgabe (September 2005) IBM Corporation, Poukeepsie, NY, abgerufen von http://publibfp.dhe.ibm.com/epubs/pdf/a227832.pdf (Abgerufen am 31. Dezember 2015)
  2. ^ "Was ist Sigbus - Objektspezifischer Hardwarefehler?".