当前位置: 首页 > news >正文

建设银行考试报名网站网站建设价格

建设银行考试报名网站,网站建设价格,网站一般用什么数据库,衡阳做网站源码基于:Linux 5.4 0. 前言 内核异常的级别大致分为三个:BUG、oops、panic。 BUG 是指那些不符合内核的正常设计,但内核能够检测出来并且对系统运行不会产生影响的问题,比如在原子上下文中休眠,在内核中用 BUG 标识。…

源码基于:Linux 5.4

0. 前言

内核异常的级别大致分为三个:BUG、oops、panic。

BUG 是指那些不符合内核的正常设计,但内核能够检测出来并且对系统运行不会产生影响的问题,比如在原子上下文中休眠,在内核中用 BUG 标识。

Oops 就意外着内核出了异常,此时会将产生异常时出错原因,CPU的状态,出错的指令地址、数据地址及其他寄存器,函数调用的顺序甚至是栈里面的内容都打印出来,然后根据异常的严重程度来决定下一步的操作:杀死导致异常的进程或者挂起系统。

panic 本意是“恐慌”的意思,这里意旨 kernel 发生了致命错误导致无法继续运行下去的情况。根据实际情况 Oops最终也可能会导致panic 的发生。

本文将简单分析下这三种异常的流程。

1. BUG()

有过驱动调试经验的人肯定都知道这个东西,这里的 BUG 跟我们一般认为的 “软件缺陷” 可不是一回事,这里说的 BUG() 其实是linux kernel中用于拦截内核程序超出预期的行为,属于软件主动汇报异常的一种机制。这里有个疑问,就是什么时候会用到呢?一般来说有两种用到的情况:

  • 一是软件开发过程中,若发现代码逻辑出现致命 fault 后就可以调用BUG()让kernel死掉(类似于assert),这样方便于定位问题,从而修正代码执行逻辑;
  • 另外一种情况就是,由于某种特殊原因(通常是为了debug而需抓ramdump),我们需要系统进入kernel panic的情况下使用;

对于 arm64 来说 BUG() 定义如下:

arch/arm64/include/asm/bug.h#ifndef _ARCH_ARM64_ASM_BUG_H
#define _ARCH_ARM64_ASM_BUG_H#include <linux/stringify.h>#include <asm/asm-bug.h>#define __BUG_FLAGS(flags)				\asm volatile (__stringify(ASM_BUG_FLAGS(flags)));#define BUG() do {					\__BUG_FLAGS(0);					\unreachable();					\
} while (0)#define __WARN_FLAGS(flags) __BUG_FLAGS(BUGFLAG_WARNING|(flags))#define HAVE_ARCH_BUG#include <asm-generic/bug.h>#endif /* ! _ARCH_ARM64_ASM_BUG_H */

注意最后的 define HAVE_ARCH_BUG ,对于arm64 架构来说,会通过 include asm-generict/bug.h 对 BUG() 进行重定义。

include/asm-generic/bug.h#ifndef HAVE_ARCH_BUG
#define BUG() do { \printk("BUG: failure at %s:%d/%s()!\n", __FILE__, __LINE__, __func__); \barrier_before_unreachable(); \panic("BUG!"); \
} while (0)
#endif#ifndef HAVE_ARCH_BUG_ON
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while (0)
#endif

也就是在 arm64 架构中 BUG() 和 BUG_ON() 都是执行的 panic()。

而对于 arm 32位架构来说,BUG() 会向CPU 下发一条未定义指令而触发ARM 发起未定义指令异常,随后进入 kernel 异常处理流程,通过调用die() 经历Oops 和 panic,下面会单独分析 die() 函数,详细看第 3 节。

2. oops

oops 意外着内核出了异常,此时会将产生异常时出错原因,CPU的状态,出错的指令地址、数据地址及其他寄存器,函数调用的顺序甚至是栈里面的内容都打印出来,然后根据异常的严重程度来决定下一步的操作:杀死导致异常的进程或者挂起系统。

例如,在编写驱动或内核模块时,常常会显示或隐式地对指针进行非法取值或使用不正确的指针,导致内核发生一个 oops 错误。当处理器在内核空间中访问一个分发的指针时,因为虚拟地址到物理地址的映射关系还没有建立,会触发一个缺页中断,在缺页中断中该地址是非法的,内核无法正确地为该地址建立映射关系,所以内核触发一个oops 错误。代码如下:

arch/arm64/mm/fault.cstatic void die_kernel_fault(const char *msg, unsigned long addr,unsigned int esr, struct pt_regs *regs)
{bust_spinlocks(1);pr_alert("Unable to handle kernel %s at virtual address %016lx\n", msg,addr);mem_abort_decode(esr);show_pte(addr);die("Oops", regs, esr);bust_spinlocks(0);do_exit(SIGKILL);
}

通过 die() 会进行oops 异常处理,详细的 die() 函数流程看第 3 节。

当出现 oops,并且如果有源码,可以通过 arm 的 arch64-linux-gnu-objdump 工具看到出错的函数的汇编情况,也可以通过 GDB 工具分析。如果出错的地方为内核函数,可以使用 vmlinux 文件。

如果没有源码,对于没有编译符号表的二进制文件,可以使用:

arch64-linux-gnu-objdump -d oops.ko

命令来转储 oops.ko 文件

内核也提供了一个非常好用的脚本,可以快速定位问题,该脚本位于 Linux 源码目录下的 scripts/decodecode 中,会把出错的 oops 日志信息转换成直观有用的汇编代码,并且告知具体出错的汇编语句,这对于分析没有源码的 oops 错误非常有用。

3. die()

arch/arm64/kernel/traps.cstatic DEFINE_RAW_SPINLOCK(die_lock);/** This function is protected against re-entrancy.*/
void die(const char *str, struct pt_regs *regs, int err)
{int ret;unsigned long flags;raw_spin_lock_irqsave(&die_lock, flags);oops_enter();console_verbose();bust_spinlocks(1);ret = __die(str, err, regs);if (regs && kexec_should_crash(current))crash_kexec(regs);bust_spinlocks(0);add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE);oops_exit();if (in_interrupt())panic("Fatal exception in interrupt");if (panic_on_oops)panic("Fatal exception");raw_spin_unlock_irqrestore(&die_lock, flags);if (ret != NOTIFY_STOP)do_exit(SIGSEGV);
}

oops_enter() ---> oops_exit() 为Oops 的处理流程,获取console 的log 级别,并通过 __die() 通过对Oops 感兴趣的模块进行callback,打印模块状态不为 MODULE_STATE_UNFORMED 的模块信息,打印PC、LR、SP、x0 等寄存器信息,打印调用栈信息,等等。

3.1 __die()

arch/arm64/kernel/traps.cstatic int __die(const char *str, int err, struct pt_regs *regs)
{static int die_counter;int ret;pr_emerg("Internal error: %s: %x [#%d]" S_PREEMPT S_SMP "\n",str, err, ++die_counter);/* trap and error numbers are mostly meaningless on ARM */ret = notify_die(DIE_OOPS, str, regs, err, 0, SIGSEGV);if (ret == NOTIFY_STOP)return ret;print_modules();show_regs(regs);dump_kernel_instr(KERN_EMERG, regs);return ret;
}
  • 打印 EMERG 的log,Internal error: oops.....;
  • notify_die() 会通知所有对 Oops 感兴趣的模块并进行callback;
  • print_modules() 打印模块状态不为 MODULE_STATE_UNFORMED 的模块信息;
  • show_regs() 打印PC、LR、SP 等寄存器的信息,同时打印调用堆栈信息;
  • dump_kernel_instr() 打印 pc指针和前4条指令;

这里不过多的剖析,感兴趣的可以查看下源码。

这里需要注意的是 notify_die() 会通知所有的Oops 感兴趣的模块,模块会通过函数 register_die_notifier() 将callback 注册到全局结构体变量 die_chain 中(多个模块注册进来形成一个链表),然后在通过 notify_die() 函数去解析这个 die_chain,并分别调用callback:

kernel/notifier.cstatic ATOMIC_NOTIFIER_HEAD(die_chain);int notrace notify_die(enum die_val val, const char *str,struct pt_regs *regs, long err, int trap, int sig)
{struct die_args args = {.regs	= regs,.str	= str,.err	= err,.trapnr	= trap,.signr	= sig,};RCU_LOCKDEP_WARN(!rcu_is_watching(),"notify_die called but RCU thinks we're quiescent");return atomic_notifier_call_chain(&die_chain, val, &args);
}
NOKPROBE_SYMBOL(notify_die);int register_die_notifier(struct notifier_block *nb)
{vmalloc_sync_mappings();return atomic_notifier_chain_register(&die_chain, nb);
}

3.2 oops同时有可能panic

从上面 die() 函数最后看到,oops_exit() 之后也有可能进入panic():

arch/arm64/kernel/traps.cvoid die(const char *str, struct pt_regs *regs, int err)
{...if (in_interrupt())panic("Fatal exception in interrupt");if (panic_on_oops)panic("Fatal exception");...
}

处于中断 或 panic_on_oops 打开时进入 panic。

中断的可能性:

  • 硬件 IRQ;
  • 软件 IRQ;
  • NMI;

panic_on_oops 的值受 CONFIG_PANIC_ON_OOPS_VALUE 影响。当然该值也可以通过节点

/proc/sys/kernel/panic_on_oops 进行动态修改。

4. panic()

panic 本意是“恐慌”的意思,这里意旨kernel发生了致命错误导致无法继续运行下去的情况。

kernel/panic.c/***	panic - halt the system*	@fmt: The text string to print**	Display a message, then perform cleanups.**	This function never returns.*/
void panic(const char *fmt, ...)
{static char buf[1024];va_list args;long i, i_next = 0, len;int state = 0;int old_cpu, this_cpu;bool _crash_kexec_post_notifiers = crash_kexec_post_notifiers;//禁止本地中断,避免出现死锁,因为无法防止中断处理程序(在获得panic锁后运行)再次被调用paniclocal_irq_disable();//禁止任务抢占preempt_disable_notrace();//通过this_cpu确认是否调用panic() 的cpu是否为panic_cpu;//即,只允许一个CPU执行该代码,通过 panic_smp_self_stop() 保证当一个CPU执行panic时,//其他CPU处于停止或等待状态;this_cpu = raw_smp_processor_id();old_cpu  = atomic_cmpxchg(&panic_cpu, PANIC_CPU_INVALID, this_cpu);if (old_cpu != PANIC_CPU_INVALID && old_cpu != this_cpu)panic_smp_self_stop();//把console的打印级别放开console_verbose();bust_spinlocks(1);va_start(args, fmt);len = vscnprintf(buf, sizeof(buf), fmt, args);va_end(args);if (len && buf[len - 1] == '\n')buf[len - 1] = '\0';//解析panic所携带的message,前缀为Kernel panic - not syncingpr_emerg("Kernel panic - not syncing: %s\n", buf);
#ifdef CONFIG_DEBUG_BUGVERBOSE/** Avoid nested stack-dumping if a panic occurs during oops processing*/if (!test_taint(TAINT_DIE) && oops_in_progress <= 1)dump_stack();
#endif//如果kgdb使能,即CONFIG_KGDB为y,在停掉所有其他CPU之前,跳转kgdb断点运行kgdb_panic(buf);if (!_crash_kexec_post_notifiers) {printk_safe_flush_on_panic();//会根据当前是否设置了转储内核(使能CONFIG_KEXEC_CORE)确定是否实际执行转储操作;//如果执行转储则会通过 kexec 将系统切换到新的kdump 内核,并且不会再返回;//如果不执行转储,则继续后面流程;__crash_kexec(NULL);//停掉其他CPU,只留下当前CPU干活smp_send_stop();} else {/** If we want to do crash dump after notifier calls and* kmsg_dump, we will need architecture dependent extra* works in addition to stopping other CPUs.*/crash_smp_send_stop();}//通知所有对panic感兴趣的模块进行回调,添加一些kmsg信息到输出atomic_notifier_call_chain(&panic_notifier_list, 0, buf);/* Call flush even twice. It tries harder with a single online CPU */printk_safe_flush_on_panic();//dump 内核log buffer中的log信息kmsg_dump(KMSG_DUMP_PANIC);/** If you doubt kdump always works fine in any situation,* "crash_kexec_post_notifiers" offers you a chance to run* panic_notifiers and dumping kmsg before kdump.* Note: since some panic_notifiers can make crashed kernel* more unstable, it can increase risks of the kdump failure too.** Bypass the panic_cpu check and call __crash_kexec directly.*/if (_crash_kexec_post_notifiers)__crash_kexec(NULL);#ifdef CONFIG_VTunblank_screen();
#endifconsole_unblank();/** We may have ended up stopping the CPU holding the lock (in* smp_send_stop()) while still having some valuable data in the console* buffer.  Try to acquire the lock then release it regardless of the* result.  The release will also print the buffers out.  Locks debug* should be disabled to avoid reporting bad unlock balance when* panic() is not being callled from OOPS.*/debug_locks_off();console_flush_on_panic(CONSOLE_FLUSH_PENDING);panic_print_sys_info();if (!panic_blink)panic_blink = no_blink;//如果sysctl配置了panic_timeout > 0则在panic_timeout后重启系统if (panic_timeout > 0) {/** Delay timeout seconds before rebooting the machine.* We can't use the "normal" timers since we just panicked.*/pr_emerg("Rebooting in %d seconds..\n", panic_timeout);for (i = 0; i < panic_timeout * 1000; i += PANIC_TIMER_STEP) {touch_nmi_watchdog();if (i >= i_next) {i += panic_blink(state ^= 1);i_next = i + 3600 / PANIC_BLINK_SPD;}mdelay(PANIC_TIMER_STEP);}}if (panic_timeout != 0) {/** This will not be a clean reboot, with everything* shutting down.  But if there is a chance of* rebooting the system it will be rebooted.*/if (panic_reboot_mode != REBOOT_UNDEFINED)reboot_mode = panic_reboot_mode;emergency_restart();}
#ifdef __sparc__{extern int stop_a_enabled;/* Make sure the user can actually press Stop-A (L1-A) */stop_a_enabled = 1;pr_emerg("Press Stop-A (L1-A) from sun keyboard or send break\n""twice on console to return to the boot prom\n");}
#endif
#if defined(CONFIG_S390)disabled_wait();
#endifpr_emerg("---[ end Kernel panic - not syncing: %s ]---\n", buf);/* Do not scroll important messages printed above */suppress_printk = 1;local_irq_enable();for (i = 0; ; i += PANIC_TIMER_STEP) {touch_softlockup_watchdog();if (i >= i_next) {i += panic_blink(state ^= 1);i_next = i + 3600 / PANIC_BLINK_SPD;}mdelay(PANIC_TIMER_STEP);}
}EXPORT_SYMBOL(panic);

详细信息见代码注释。


文章转载自:
http://dinncowidowhood.tpps.cn
http://dinncosnowcap.tpps.cn
http://dinncoisabelline.tpps.cn
http://dinncoshamus.tpps.cn
http://dinncopremed.tpps.cn
http://dinncodraftiness.tpps.cn
http://dinncooceanfront.tpps.cn
http://dinncotemplate.tpps.cn
http://dinncolincolnesque.tpps.cn
http://dinncotgif.tpps.cn
http://dinncoslipware.tpps.cn
http://dinncopanne.tpps.cn
http://dinncospinel.tpps.cn
http://dinncoovercommit.tpps.cn
http://dinncouneducated.tpps.cn
http://dinncoadusk.tpps.cn
http://dinncoflummery.tpps.cn
http://dinncoinitiatrix.tpps.cn
http://dinncoinvertase.tpps.cn
http://dinncoparashah.tpps.cn
http://dinncofantabulous.tpps.cn
http://dinncodicotyl.tpps.cn
http://dinncobent.tpps.cn
http://dinncosonneteer.tpps.cn
http://dinncoovertrump.tpps.cn
http://dinncooperate.tpps.cn
http://dinncoattorneyship.tpps.cn
http://dinncorevivify.tpps.cn
http://dinncoelectrodiagnosis.tpps.cn
http://dinncoparentally.tpps.cn
http://dinncogalatia.tpps.cn
http://dinncofraternization.tpps.cn
http://dinncofoa.tpps.cn
http://dinncoclaustral.tpps.cn
http://dinncocrosslet.tpps.cn
http://dinncolineskipper.tpps.cn
http://dinncogaita.tpps.cn
http://dinncocoverture.tpps.cn
http://dinncosqualene.tpps.cn
http://dinncodoline.tpps.cn
http://dinncoknave.tpps.cn
http://dinncosaseno.tpps.cn
http://dinncoanarchism.tpps.cn
http://dinncoannoit.tpps.cn
http://dinncosalt.tpps.cn
http://dinncotelelens.tpps.cn
http://dinncocalculated.tpps.cn
http://dinncogynandrous.tpps.cn
http://dinncofeldsher.tpps.cn
http://dinncounblamable.tpps.cn
http://dinncomome.tpps.cn
http://dinncoantiadministration.tpps.cn
http://dinncobrains.tpps.cn
http://dinncogreed.tpps.cn
http://dinncoinchage.tpps.cn
http://dinncoatmospheric.tpps.cn
http://dinncocylix.tpps.cn
http://dinncophosphorylate.tpps.cn
http://dinncooliguresis.tpps.cn
http://dinncoacanthoid.tpps.cn
http://dinncoburning.tpps.cn
http://dinncofarmworker.tpps.cn
http://dinncosting.tpps.cn
http://dinncoorganophosphorous.tpps.cn
http://dinncoroundish.tpps.cn
http://dinncosouse.tpps.cn
http://dinncoineluctable.tpps.cn
http://dinncomanado.tpps.cn
http://dinncofoofaraw.tpps.cn
http://dinncocowlstaff.tpps.cn
http://dinncotowhead.tpps.cn
http://dinncodistractingly.tpps.cn
http://dinncokinaesthesia.tpps.cn
http://dinncosarcenet.tpps.cn
http://dinncosoucar.tpps.cn
http://dinncoexorbitancy.tpps.cn
http://dinncocountermissile.tpps.cn
http://dinncosinitic.tpps.cn
http://dinncohqmc.tpps.cn
http://dinncoattestative.tpps.cn
http://dinncodish.tpps.cn
http://dinncochinoperl.tpps.cn
http://dinncosansevieria.tpps.cn
http://dinncointermedin.tpps.cn
http://dinncoacetated.tpps.cn
http://dinncopack.tpps.cn
http://dinncosplurge.tpps.cn
http://dinncochiliasm.tpps.cn
http://dinncocyclorama.tpps.cn
http://dinncocockade.tpps.cn
http://dinncoreunify.tpps.cn
http://dinncoandrogenize.tpps.cn
http://dinncovittoria.tpps.cn
http://dinncoimplausibly.tpps.cn
http://dinncoloathy.tpps.cn
http://dinncoflocculation.tpps.cn
http://dinncoshite.tpps.cn
http://dinncotrimaran.tpps.cn
http://dinncovpn.tpps.cn
http://dinncoheadkerchief.tpps.cn
http://www.dinnco.com/news/121048.html

相关文章:

  • 医院网站建设解决方案北京网站优化方法
  • 潢川网站建设公司百度app最新版本
  • 做网站的体会东莞寮步最新通知
  • 想找私人做网站嘉兴seo排名外包
  • 米拓建设网站2024年重大政治时事汇总
  • 长春制作网站企业写软文的app
  • 拥有响应式网站营销型网站策划方案
  • 科技设计公司网站模板下载it教育培训机构排名
  • 网站2级目录怎么做的网页模板源代码
  • 山西省建设厅招标网站首页网络营销主要学什么
  • 自己做网站怎么做的网络营销考试答案
  • 不同程序建的网站风格企业营销战略
  • seo优化培训学校优化大师下载安装免费
  • 网站建设销售招聘百度号码认证平台官网
  • 软文营销把什么放在第一位电子商务seo是什么意思
  • 怎么做网站框架北京seo优化外包
  • 媒体宣传百度seo优化是做什么的
  • 江苏建发建设项目咨询有限公司网站网络营销案例实例
  • 提供网站制作公司入门seo技术教程
  • 网络营销方式有浙江专业网站seo
  • 建设网站上申请劳务资质吗山西百度推广开户
  • 上海装修公司一览表网站排名seo
  • 宿迁网站建设公司良品铺子网络营销策划书
  • 熊掌号做网站推广的注意事项软文营销案例200字
  • 大连模板建站软件互联网营销策划是做什么的
  • 南昌网站建设价格游戏推广赚钱
  • 德惠网站建设免费接单平台
  • 晋城市城乡建设局网站seo搜索优化网站推广排名
  • 学网站开发工程师难学吗青岛seo培训
  • 昆明360网站制作游戏优化