Oops诞生记[转自网络,作者不祥,收藏之]
来源:互联网 发布:施工方案编制软件 编辑:程序博客网 时间:2024/05/17 06:48
常在河边走,哪能不湿鞋。用Linux,总有死机的时候,如果运气好,会看到一些所谓"Oops"信息(在屏幕上或系统日志中),比如:
Unable to handle kernel paging request at virtual address f899b670
printing eip:
c01de48c
*pde = 00737067
Oops: 0002 [#1]
Moduleslinked in: bluesmoke_e752x bluesmoke_mc md5 ipv6 parport_pc lp parportnls_cp936 vfat fat dm_mod button battery asus_acpi ac joydevyenta_socket pcmcia_core uhci_hcd ehci_hcd snd_intel8x0 snd_ac97_codecsnd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_allocsnd_mpu401_uart snd_rawmidi snd_seq_device snd soundcore ipw2200ieee80211 ieee80211_crypt sk98lin ext3 jbd
CPU: 0
EIP: 0060:[] Not tainted VLI
EFLAGS: 00210286 (2.6.9-11.21AXKProbes)
EIP is at kobject_add+0x83/0xd7
eax: c038db78 ebx: c038db04 ecx: f899b670 edx: f8a4a630
esi: c038db4c edi: f8a4a614 ebp: c038db80 esp: d7568f2c
ds: 007b es: 007b ss: 0068
Process modprobe (pid: 8227, threadinfo=d7568000 task=f4ea99b0)
Stack: f8a4a614 ffffffea f8a4a5e4 00000000 c01de4f9 f8a4a614 c038db00 c024a1d4
f8a4a5c0 f8a4a5e4 f8a4a5f4 d7568000 c024a661 1d244b3c 00000000 0000000a
c032421b 00000000 00000000 00000015 00000014 00000016 f89ddb34 f8a4a5c0
Call Trace:
[] kobject_register+0x19/0x39
[] bus_add_driver+0x36/0x97
[] driver_register+0x82/0x89
[] pci_register_driver+0x85/0xa1
[] init_module+0xa/0x14 [bluesmoke_e752x]
[] sys_init_module+0x1ec/0x323
[] syscall_call+0x7/0xb
Code:85 d2 0f 85 06 04 00 00 85 ed 75 0d 8b 47 28 83 c0 10 e8 82 01 00 00 89c5 8b 47 28 8d 57 1c 83 c0 08 89 47 1c 8b 48 04 89 50 04 <89> 1189 4a 04 8b 47 28 8b 18 8d 4b 48 89 c8 ba ff ff 00 00 0f
Oops可以看成是内核级的SegmentationFault。应用程序如果进行了非法内存访问或执行了非法指令,会得到Segfault信号,一般的行为是coredump,应用程序也可以自己截获Segfault信号,自行处理。如果内核自己犯了这样的错误,则会打出Oops信息。
有不少文章说明如何理解这些Oops,这里只想解释一下它所产生的过程(以2.6系列内核为例):
首先是处理硬件发出的内存访问异常(fault),有些异常是无辜的(比如demand-paging),而有些则是内核的错误所致。
1. do_page_fault() arch/i386/mm/fault.c
如果是内核进行了非法访问,do_page_fault()会先打出EIP, PDE等信息,例如:
Unable to handle kernel paging request at virtual address f899b670
printing eip:
c01de48c
*pde = 00737067
然后调用 die("Oops", regs, error_code);
这之后,如果系统还活着(至少要满足两个条件:1. 在进程上下文 2. 没有设置panic_on_oops),会杀死当前进程。然后继续运行,好像什么事情都没有发生一样。不过,这样的好事不经常发生,发生了也不会太持久。
2. do_page_fault() -> die() arch/i386/kernel/traps.c
die() 首先打出一行:
Oops: 0002 [#1]
其中0002代表错误码 (读错误、发生在内核空间),#1代表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
然后,调用 show_registers(regs) 输出寄存器、当前进程、堆栈、指令代码等信息:
Modules linked in: bluesmoke_e752x bluesmoke_mc md5 ipv6 parport_pc lpparport nls_cp936 vfat fat dm_mod button battery asus_acpi ac joydevyenta_socket pcmcia_core uhci_hcd ehci_hcd snd_intel8x0 snd_ac97_codecsnd_pcm_oss snd_mixer_oss snd_pcm snd_timer snd_page_allocsnd_mpu401_uart snd_rawmidi snd_seq_device snd soundcore ipw2200ieee80211 ieee80211_crypt sk98lin ext3 jbd
CPU: 0
EIP: 0060:[] Not tainted VLI
EFLAGS: 00210286 (2.6.9-11.21AXKProbes)
EIP is at kobject_add+0x83/0xd7
eax: c038db78 ebx: c038db04 ecx: f899b670 edx: f8a4a630
esi: c038db4c edi: f8a4a614 ebp: c038db80 esp: d7568f2c
ds: 007b es: 007b ss: 0068
Process modprobe (pid: 8227, threadinfo=d7568000 task=f4ea99b0)
Stack: f8a4a614 ffffffea f8a4a5e4 00000000 c01de4f9 f8a4a614 c038db00 c024a1d4
f8a4a5c0 f8a4a5e4 f8a4a5f4 d7568000 c024a661 1d244b3c 00000000 0000000a
c032421b 00000000 00000000 00000015 00000014 00000016 f89ddb34 f8a4a5c0
Call Trace:
[] kobject_register+0x19/0x39
[] bus_add_driver+0x36/0x97
[] driver_register+0x82/0x89
[] pci_register_driver+0x85/0xa1
[] init_module+0xa/0x14 [bluesmoke_e752x]
[] sys_init_module+0x1ec/0x323
[] syscall_call+0x7/0xb
Code:85 d2 0f 85 06 04 00 00 85 ed 75 0d 8b 47 28 83 c0 10 e8 82 01 00 00 89c5 8b 47 28 8d 57 1c 83 c0 08 89 47 1c 8b 48 04 89 50 04 <89> 1189 4a 04 8b 47 28 8b 18 8d 4b 48 89 c8 ba ff ff 00 00 0f
如果是在中断上下文,则直接调用panic()。如果是在进程上下文,则根据panic_on_oops的设置选择是否panic()。panic_on_oops的缺省设置是"0",即在Oops发生时不会进行panic()操作。可以通过sysctl进行设置:
sysctl -w kernel.panic_on_oops=1
有panic_on_oops这样的设置,说明Oops不一定导致系统死亡,也不一定需要重新启动系统。正如用户程序segfault时可能还能坚持运行一样。不过Oops一旦发生,系统已经有些不正常了,即使表面上可能还正常,不过可能有些锁已经被占用而无法释放,很快会导致系统死锁。
那么,panic()是什么呢?panic()和用户空间的abort()类似,简单清理一下,就可以放心去死(reboot)了。
3. do_page_fault() -> die() -> panic()
panic会根据 kernel.panic 的设置决定 reboot 前的延时,如果 kernel.panic=0,则打开中断,陷入死循环。反之,则在几秒之后,reboot系统。
可以看出虽然都是死,但死因不同,死亡时的表现更是五花八门。常见的死因有:
- 非法内存访问 (比如访问地址0)
- 非法指令
有时候核心成心发出非法指令,比如BUG() (include/asm/bug.h) 中所做的,以引起Oops。类似用户程序中调用assert()。
死亡发生的地点也很关键,直接导致了死亡的不同表现,比如:
- 进程上下文
- 中断上下文
在中断上下文中,由于中断是关闭的,而且往往会占用一些锁,这种情况下一般除了死,没有什么别的办法。
在进程上下文中要自由一些,如果运气好的话,可以苟延残喘一段时间。
- Oops诞生记[转自网络,作者不祥,收藏之]
- Oops的诞生
- Oops的诞生
- Oops的诞生
- 如何网络成瘾 - 作者:貘貘(转自GameRes论坛)
- WinCE BSP中的Dirs文件和Sources文件(转自微软MVP作者:ARM—WinCE) 收藏
- 找工作经验贴----转自cc98 (作者ID:qzz88 ) 仅为收藏,感谢原作者的经验分享
- Hibernate 学习之[hibernate的原理][转自http://www.sin-oil.com/oil/article.asp?id=182 作者:daxing22 ]
- 利用MVC模式开发Java应用程序(转自网络,作者龚赤兵)
- Windows网络体系结构总结(转自看雪,作者:jbwang)
- 利用MVC模式开发Java应用程序(转自网络,作者龚赤兵)
- oops错误分析文章收藏
- RecyclerView局部刷新爬坑之路 转自 :作者:Hoolly,腾讯移动客户端开发工程师。
- 转自:tanghui19900420作者。线程理论基础
- 谈谈我对读研和软件学院的看法(转自网络,作者不太清楚)
- android自定义View之钟表诞生记
- 在VCKBASE上读到《一种漂亮的自绘菜单》 [作者:郑恒 (lbird)]
- 收藏的blog作者地址
- PATH——路径设置命令
- Linux下的压缩解压缩命令详解
- 没有create,能不能alter
- "foo", "bar", "foobar" 的意思
- DELTREE——删除整个目录命令
- Oops诞生记[转自网络,作者不祥,收藏之]
- DirectShow技术介绍(长篇)-1
- C#中timer类
- COALESCE
- 【转】MyEclipse 8.6 优化 与 SVN安装
- DirectShow技术介绍(长篇)-2
- 网络安全
- Binding
- Doxygen - Doxygen简介