Rumah > Artikel > Tutorial sistem > Maklumat pengecualian dalam kernel Linux: Penjelasan terperinci tentang Oops
Oops ialah mesej ralat khas dalam kernel Linux Ia digunakan untuk menunjukkan bahawa pengecualian tidak membawa maut telah berlaku dalam kernel, seperti penyahrujukan penunjuk nol, akses memori yang tidak sah, ralat bahagi-dengan-sifar, dsb. Kejadian Oops biasanya bermakna terdapat pepijat dalam kernel atau masalah dengan pemandu, yang boleh menyebabkan ketidakstabilan atau ranap sistem. Dalam artikel ini, kami akan memperkenalkan prinsip dan ciri Oops dalam kernel Linux, termasuk format, kandungan, sebab, klasifikasi, dsb. Oops, dan memberikan contoh penggunaan dan langkah berjaga-jaganya.
Apakah itu Oops dalam pembangunan kernel Linux? Sebenarnya, tidak ada perbezaan penting antaranya dan penjelasan di atas, kecuali protagonis yang bercakap menjadi Linux. Apabila beberapa lagi masalah maut berlaku, kernel Linux kami juga akan berkata kepada kami dengan memohon maaf: "Op, saya minta maaf, saya membuat kesilapan." Apabila panik kernel berlaku, kernel Linux akan mencetak maklumat Oops dan menunjukkan kepada kami status daftar semasa, kandungan tindanan dan jejak Panggilan lengkap, yang boleh membantu kami mencari ralat.
Sekarang, mari lihat contoh. Untuk menyerlahkan protagonis artikel ini - Oops, satu-satunya fungsi contoh ini adalah untuk mencipta ralat rujukan penunjuk nol.
#include #include static int __init hello_init(void) { int *p = 0; *p = 1; return 0; } static void __exit hello_exit(void) { return; } module_init(hello_init); module_exit(hello_exit); MODULE_LICENSE("GPL");
Jelas sekali, ralatnya ialah baris 8.
Seterusnya, kami menyusun modul ini dan menggunakan insmod untuk memasukkannya ke dalam ruang kernel Seperti yang kami jangkakan, Oops muncul.
“
[ 100.243737] BUG: tidak dapat mengendalikan penolakan penunjuk NULL kernel di (null)
[100.244985] IP: [] hello_init+0x5/0x11 [hello]
[ 100.262266] *pde = 00000000
[100.288395] Op: 0002 [#1] SMP
[100.305468] fail sysfs terakhir: /sys/devices/virtual/sound/timer/uevent
[ 100.325955] Modul dipautkan dalam: hello(+) vmblock vsock vmmemctl vmhgfs acpiphp snd_ens1371 gameport snd_ac97_codec ac97_bus snd_pcm_oss snd_mixer_p_ssnd_ssnd_scm se q_midi snd_rawmidi snd_seq_midi_event snd_seq snd_timer snd_seq_device ppdev psmouse serio_raw fbcon tileblit font bitblit softcursor snd parport_pc soundcore snd_page_alloc vmci vmci i2c_6fixb4 agpgart shpchp lp parport floppy pcnet32 mii mptspi mptscsih mptbase scsi_transport_spi vmxnet
[ 100.472178] [ 100.494931] Pid: 1586, kom: insmod Tidak tercemar (2.6.32-21-generik #32-Ubuntu) Platform Maya VMware
[100.540018] EIP: 0060:[] EFLAGS: 00010246 CPU: 0
[ 100.562844] EIP berada di hello_init+0x5/0x11 [hello]
[ 100.584351] EAX: 00000000 EBX: ffffffffc ECX: f82cf040 EDX: 00000001
[ 100.609358] ESI: f82cf040 EDI: 00000000 EBP: f1b9ff5c ESP: f1b9ff5c
[ 100.631467] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 100.657664] Proses insmod (pid: 1586, ti=f1b9e000 task=f137b340 task.ti=f1b9e000)
[100.706083] Timbunan:
[ 100.731783] f1b9ff88 c0101131 f82cf040 c076d240 fffffffc f82cf040 0072cff4 f82d2000
[100.759324]fffffffc f82cf040 0072cff4 f1b9ffac c0182340 f19638f8 f137b340 f19638c0
[100.811396]00000004 09cc9018 09cc9018 00020000 f1b9e000 c01033ec 09cc9018 00015324
[100.891922] Jejak Panggilan:
[ 100.916257] [] ? do_one_initcall+0x31/0x190
[ 100.943670] [] ?
[ 100.970905] [] ?
[ 100.995542] [] ?[ 101.024087] Kod: 05 00 00 00 00 01 00 00 00 5d c3 00 00 00 00 00 00 00 00 00 00
[ 101.079592] EIP: [] hello_init+0x5/0x11 [hello] SS:ESP 0068:f1b9ff5c
[101.134682] CR2: 0000000000000000
[ 101.158929] —[ jejak tamat e294b69a66d752cb ]—
”Op mula-mula menerangkan jenis pepijat ini, dan kemudian menunjukkan lokasi pepijat berlaku, iaitu "IP: [] hello_init+0x5/0x11 [hello]".
Di sini, kita perlu menggunakan objdump alat bantu untuk membantu menganalisis masalah. objdump boleh digunakan untuk membuka, format arahan adalah seperti berikut:
“objdump -S hello.o
”
下面是hello.o反汇编的结果,而且是和C代码混排的,非常的直观。
hello.o: file format elf32-i386 Disassembly of section .init.text: 00000000 : #include #include static int __init hello_init(void) { 0: 55 push %ebp int *p = 0; *p = 1; return 0; } 1: 31 c0 xor %eax,%eax #include #include static int __init hello_init(void) { 3: 89 e5 mov %esp,%ebp int *p = 0; *p = 1; 5: c7 05 00 00 00 00 01 movl $0x1,0x0 c: 00 00 00 return 0; } f: 5d pop %ebp 10: c3 ret Disassembly of section .exit.text: 00000000 : static void __exit hello_exit(void) { 0: 55 push %ebp 1: 89 e5 mov %esp,%ebp 3: e8 fc ff ff ff call 4 return; } 8: 5d pop %ebp 9: c3 ret
对照Oops的提示,我们可以很清楚的看到,出错的位置hello_init+0x5的汇编代码是:
5:c7 05 00 00 00 00 01 movl $0x1,0x0
这句代码的作用是把数值1存入0这个地址,这个操作当然是非法的。
我们还能看到它对应的c代码是:
*p = 1;
Bingo!在Oops的帮助下我们很快就解决了问题。
我们再回过头来检查一下上面的Oops,看看Linux内核还有没有给我们留下其他的有用信息。
“
Oops: 0002 [#1]
”
这里面,0002表示Oops的错误代码(写错误,发生在内核空间),#1表示这个错误发生一次。
Oops的错误代码根据错误的原因会有不同的定义,本文中的例子可以参考下面的定义(如果发现自己遇到的Oops和下面无法对应的话,最好去内核代码里查找):
“
* error_code:
* bit 0 == 0 means no page found, 1 means protection fault
* bit 1 == 0 means read, 1 means write
* bit 2 == 0 means kernel, 1 means user-mode
* bit 3 == 0 means data, 1 means instruction”
有时候,Oops还会打印出Tainted信息。这个信息用来指出内核是因何种原因被tainted(直译为“玷污”)。具体的定义如下:
“
1: ‘G’ if all modules loaded have a GPL or compatible license, ‘P’ if any proprietary module has been loaded. Modules without a MODULE_LICENSE or with a MODULE_LICENSE that is not recognised by insmod as GPL compatible are assumed to be proprietary.
2: ‘F’ if any module was force loaded by “insmod -f”, ‘ ‘ if all modules were loaded normally.
3: ‘S’ if the oops occurred on an SMP kernel running on hardware that hasn’t been certified as safe to run multiprocessor. Currently this occurs only on various Athlons that are not SMP capable.
4: ‘R’ if a module was force unloaded by “rmmod -f”, ‘ ‘ if all modules were unloaded normally.
5: ‘M’ if any processor has reported a Machine Check Exception, ‘ ‘ if no Machine Check Exceptions have occurred.
6: ‘B’ if a page-release function has found a bad page reference or some unexpected page flags.
7: ‘U’ if a user or user application specifically requested that the Tainted flag be set, ‘ ‘ otherwise.
8: ‘D’ if the kernel has died recently, i.e. there was an OOPS or BUG.
9: ‘A’ if the ACPI table has been overridden.
10: ‘W’ if a warning has previously been issued by the kernel. (Though some warnings may set more specific taint flags.)
11: ‘C’ if a staging driver has been loaded.
12: ‘I’ if the kernel is working around a severe bug in the platform firmware (BIOS or similar).”
Pada asasnya, maklumat Tainted ini dikhaskan untuk pembangun kernel. Jika pengguna menghadapi Oops semasa menggunakan Linux, mereka boleh menghantar kandungan Oops kepada pembangun kernel untuk penyahpepijatan Berdasarkan maklumat Tercemar ini, pembangun kernel mungkin boleh menentukan persekitaran di mana kernel sedang berjalan apabila kernel panik. Jika kita hanya menyahpepijat pemandu kita sendiri, maklumat ini tidak akan bermakna.
Contoh dalam artikel ini adalah sangat mudah selepas Oops berlaku, jadi kami boleh melihat maklumat lengkap dari dmesg. Tetapi lebih kerap daripada tidak, sistem akan mati apabila Oops berlaku Pada masa ini, mesej ralat ini tidak mempunyai masa untuk disimpan dalam fail, dan ia tidak dapat dilihat lagi selepas mematikan kuasa. Kami hanya boleh merakamnya dengan cara lain: tulisan tangan atau mengambil gambar.
Terdapat situasi yang lebih teruk Jika terdapat terlalu banyak maklumat Oops, skrin satu halaman tidak akan dipaparkan sepenuhnya. Kaedah pertama ialah menggunakan parameter vga dalam grub untuk menentukan resolusi yang lebih tinggi supaya skrin boleh memaparkan lebih banyak kandungan. Jelas sekali, kaedah ini sebenarnya tidak dapat menyelesaikan terlalu banyak masalah; kaedah kedua ialah menggunakan dua mesin untuk mencetak maklumat Oops mesin nyahpepijat ke skrin hos melalui port bersiri. Tetapi kebanyakan komputer riba kini tidak mempunyai port bersiri, dan penyelesaian ini juga mempunyai had yang besar; kaedah ketiga ialah menggunakan alat pembuangan kernel kdump untuk membuang kandungan memori dan daftar CPU apabila Oops berlaku ke dalam fail gdb untuk menganalisis masalah.
Masalah yang mungkin anda hadapi dalam proses membangunkan pemacu kernel adalah semua jenis pelik, dan kaedah penyahpepijatan juga pelbagai Oops adalah peringatan yang diberikan kepada kami oleh kernel Linux, dan kami mesti menggunakannya dengan baik.
Melalui artikel ini, kami telah mempelajari tentang prinsip dan ciri Oops dalam kernel Linux, yang boleh digunakan untuk mendiagnosis dan menyahpepijat masalah dalam kernel. Kita harus memilih alatan yang sesuai berdasarkan keperluan sebenar dan mengikut beberapa prinsip asas, seperti menyimpan dan menganalisis maklumat Oops, menggunakan jadual simbol dan kod sumber untuk mencari masalah, menggunakan parameter modul dan parameter kernel untuk melaraskan tingkah laku kernel, dsb. Oops ialah mesej ralat biasa dalam kernel Linux Ia boleh mencerminkan status dan pengecualian kernel, dan juga boleh meningkatkan kualiti dan kestabilan kernel. Saya harap artikel ini dapat membantu dan memberi inspirasi kepada anda.
Atas ialah kandungan terperinci Maklumat pengecualian dalam kernel Linux: Penjelasan terperinci tentang Oops. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!