Oops

Czasem z powodu błędu albo nieprawidłowo działającego sprzętu w kernelu pojawia się Oops. Oznacza to, że pojawiła się nieoczekiwana sytuacja i trzeba zadziałać. Następuje wtedy:

Błąd oops nie musi oznaczać uszkodzenia systemu, czasem system potrafi sam rozwiązać problem. Jeżeli jednak system nie potrafi poradzić sobie z problemem, wyświetli komunikat kernel panic i przestanie działać.

kernel panic to akcja podejmowana przez system operacyjny po wykryciu krytycznego błędu wewnętrznego którego nie można naprawić. Jądro wypisuje komunikat o błędzie, robi zrzut pamięci w celu późniejszej diagnozy, a natępnie rebootuje maszynę lub wchodzi w nieskończoną pętlę.

Oops jest raportem z bugu w jądrze, np. kiedy jądro próbuje dostać się do niepoprawnego adresu pamięci. Nie koniecznie musi to oznaczać błąd programistów - źle działający hardware również może go spowodować.

Niektóre sytuacje mogą być tak fatalne że komunikat Oops nie zostanie zapisany w logu. W takiej sytuacji trzeba ustawić zdalną konsolę aby próbować taką oopsa wyłowić (narzędzia kdb, kgdb - obydwa omówione później).

W architekturze x86 oops może zawierać następujące informacje:

Użytkownik może wykryć oops dzięki komunikatowi o błędzie wyświetlanemu w konsoli systemowej. Zwykle w systemie pracuje demon logujący (klogd, syslogd), przez co wiadomość może być (o ile sytuacja nie była TOTALNIE krytyczna) znaleziona w /var/log/messages. Przykład:

Unable to handle kernel NULL pointer dereference at virtual address 00000000
 printing eip:
c018c3c8
*pde = 00000000
Oops: 0000 [#1]
Modules linked in: vznetdev vzmon af_packet simfs vfat fat loop vzdquota
ipt_length ipt_ttl ipt_tcpmss ipt_TCPMSS iptable_mangle ipt_multiport ipt_limit
ipt_tos ipt_REJECT iptable_filter ip_tables i2c_dev i2c_core sunrpc vzdev
thermal processor fan button battery asus_acpi ac uhci_hcd ehci_hcd usbcore
e100 mii floppy
CPU:    0, VCPU: 0:0
EIP:    0060:[<c018c3c8>]    Not tainted
EFLAGS: 00010203   (2.6.8-022stab077.1) 
EIP is at vfs_quota_on_file+0x1f8/0x350
eax: 00000000   ebx: f3fd6ca8   ecx: f3f8b124   edx: 00000000
esi: f3fd6c00   edi: c6500e40   ebp: f4c2a19c   esp: c0c9fe40
ds: 007b   es: 007b   ss: 0068
Process quotaon (pid: 2802, veid=0, threadinfo=c0c9f000 task=ec39ecc0)
Stack: f3fd6c00 00000000 00000101 f3fd6ccc f3f8b124 00000022 ffffffea f3f8b0b4 
       f3d8e89c 00000010 c6500e40 f32ac000 00800002 00000002 c018c578 c6500e40 
       00000000 00000002 f3fd6c00 f32ac000 c01d8681 f3fd6c00 00000000 00000002 
Call Trace:
 [<c018c578>] vfs_quota_on+0x58/0x80
 [<c01d8681>] ext3_quota_on+0xb1/0x100
 [<c016d79b>] link_path_walk+0x76b/0xd30
 [<c016c8a6>] getname+0x76/0xc0
 [<c018e9c2>] do_quotactl+0x292/0x520
 [<c0176df5>] dput+0x25/0x30
 [<c016cb75>] path_release+0x15/0x50
 [<c0167eeb>] lookup_bdev+0x6b/0xc0
 [<c01345dc>] uncharge_dcache+0x2c/0x40
 [<c016c8a6>] getname+0x76/0xc0
 [<c018ecc0>] quota_get_sb+0x70/0x80
 [<c018f56d>] sys_quotactl+0x8d/0xd9
 [<c03fc2ef>] syscall_call+0x7/0xb
Code: ff 10 85 c0 0f 84 20 01 00 00 8b 4c 24 1c ba 01 00 ff ff 8b

W kodzie możemy znaleźć makra które służą do sygnalizowania nietypowej sytuacji, są to:

BUG()
BUG_ON()

Ich implementacja wygląda następująco (include/asm-generic/bug.h):

#define BUG() do { \
   printk("BUG: failure at %s:%d/%s()!\n"__FILE____LINE__, __FUNCTION__); \
   panic("BUG!"); \
while (0)

#define BUG_ON(condition) do { if (unlikely((condition)!=0)) BUG(); } while (0)

Umieszczając w kodzie naszego modułu makro BUG() możemy wywołać sytuację skutkującą wypisaniem komunikatu o błędzie.

ksymoops (jądra 2.4)

Do tłumaczenia wiadomości oops, m.in. adresów i kodu na odpowiadające im symbole służy narzędzie ksymoops (znajdujące się w pakiecie o tej samej nazwie). Próbuje ono przetłumaczyć adresy na nazwy funkcji korzystając z informacji zawartych w:

Można też wskazać inne lokalizacje ich odpowiedników - opcje uruchomienia programu.

Przykład komunikatu o błędzie:

CPU:    0
EIP:    0010:<c011933c>    Tainted: P
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010002
eax: 00000ce0   ebx: 00001000   ecx: c778a510   edx: 00000610
esi: 00000002   edi: 00000000   ebp: c02165c0   esp: c6663f58
ds: 0018   es: 0018   ss: 0018
Process pcmcia (pid: 1003, stackpage=c6663000)
Stack: 00000000 c02165a0 00000000 c02165c0 c6663fc4 c01193cf c010ac96 c0116406
       c0116340 00000000 00000001 c02165c0 fffffffe c011616a c02165c0 00000000
       c0214900 00000000 c6663fbc 00000046 c010817d 00000000 080caa18 00000000
Call Trace: 
Code: 89 42 04 89 10 c7 41 04 00 00 00 00 c7 01 00 00 00 00 fb 53
Ten sam komunikat przetłumaczony przez ksymoops:
  EIP; c0113f8c <sys_init_module+49c/4d0>
  Trace; c011d3f5 <sys_mremap+295/370>
  Trace; c011af5f <do_generic_file_read+5bf/5f0>
  Trace; c011afe9 <file_read_actor+59/60>
  Trace; c011d2bc <sys_mremap+15c/370>
  Trace; c010e80f <do_sigaltstack+ff/1a0>
  Trace; c0107c39 <overflow+9/c>
  Trace; c0107b30 <tracesys+1c/23>

Jądra 2.6 nie potrzebują ksymoops

Od wersji 1.3-p13 pakietu sysklogd, demon klogd automatycznie tłumaczy najważniejsze adresy na odpowiadające im wartości symboliczne

Przetłumaczona w ten sposób wiadomość jest zapisywana w logu (może być także wyświetlona użytkownikowi). Tłumaczenie adresów statycznych odbywa się w niemal identyczny sposób jak ksymoops. Jedynym warunkiem jest jednak odnalezienie pliku z symbolami w momencie uruchamiania demona.

Źródła: