kernel回归,KERNEL

http://www.itjxue.com  2023-01-22 09:46  来源:未知  点击次数: 

linux 一个核 kernal panic后,其他核怎么办

1. Linux Kernel Panic的产生的原因

panic是英文中是惊慌的意思,Linux Kernel panic正如其名,linux kernel不知道如何走了,它会尽可能把它此时能获取的全部信息都打印出来。

有两种主要类型kernel panic,后面会对这两类panic做详细说明:

1.hard panic(也就是Aieee信息输出)

2.soft panic (也就是Oops信息输出)

2. 常见Linux Kernel Panic报错内容:

(1) Kernel panic-not syncing fatal exception in interrupt

(2) kernel panic – not syncing: Attempted to kill the idle task!

(3) kernel panic – not syncing: killing interrupt handler!

(4) Kernel Panic – not syncing:Attempted to kill init !

3. 什么会导致Linux Kernel Panic?

只有加载到内核空间的驱动模块才能直接导致kernel panic,你可以在系统正常的情况下,使用lsmod查看当前系统加载了哪些模块。

除此之外,内建在内核里的组件(比如memory map等)也能导致panic。

因为hard panic和soft panic本质上不同,因此我们分别讨论。

4. hard panic

一般出现下面的情况,就认为是发生了kernel panic:

机器彻底被锁定,不能使用

数字键(Num Lock),大写锁定键(Caps Lock),滚动锁定键(Scroll Lock)不停闪烁。

如果在终端下,应该可以看到内核dump出来的信息(包括一段”Aieee”信息或者”Oops”信息)

和Windows蓝屏相似

4.1 原因

对于hard panic而言,最大的可能性是驱动模块的中断处理(interrupt handler)导致的,一般是因为驱动模块在中断处理程序中访问一个空指针(null pointre)。一旦发生这种情况,驱动模块就无法处理新的中断请求,最终导致系统崩溃。

本人就曾遇到过这样一个例子:在多核系统中,包括AP应用处理器、mcu微控制器和modem处理器等系统中,mcu控制器用于系统的低功耗控制,mcu微控制器由于某种原因超时向AP应用处理器发送一个超时中断,AP接受中断后调用中断处理函数读取mcu的状态寄存器,发现是mcu的超时中断,就在中断处理程序中主动引用一个空指针,迫使AP处理器打印堆栈信息然后重启linux系统。这就是一个典型的hard panic,这里不对mcu超时原因做深入的分析,只是用来说明hard panic产生的机理。

3.2 信息收集

根据panic的状态不同,内核将记录所有在系统锁定之前的信息。因为kenrel panic是一种很严重的错误,不能确定系统能记录多少信息,下面是一些需要收集的关键信息,他们非常重要,因此尽可能收集全,当然如果系统启动的时候就kernel panic,那就无法只知道能收集到多少有用的信息了。

/var/log/messages: 幸运的时候,整个kernel panic栈跟踪信息都能记录在这里,当然对于嵌入式linux系统,kernel panic的内核打印信息被放到/data/dontpanic目录下,包括两个文件:apanic_console存放的是内核控制台的log,apanic_threads存放的是linux kernel发生panic时的所有内核线程的堆栈信息。

应用程序/库 日志: 可能可以从这些日志信息里能看到发生panic之前发生了什么。

其他发生panic之前的信息,或者知道如何重现panic那一刻的状态

终端屏幕dump信息,一般OS被锁定后,复制,粘贴肯定是没戏了,因此这类信息,你可以需要借助数码相机或者原始的纸笔工具了。

如果kernel dump信息既没有在/var/log/message里,也没有在屏幕上,那么尝试下面的方法来获取(当然是在还没有死机的情况下):

如果在图形界面,切换到终端界面,dump信息是不会出现在图形界面的,甚至都不会在图形模式下的虚拟终端里。

确保屏幕不黑屏,可以使用下面的几个方法:

setterm -blank 0

setterm -powerdown 0

setvesablank off

从终端,拷贝屏幕信息(方法见上)

实际上,当内核发生panic时,linux系统会默认立即重启系统,当然这只是默认情况,除非你修改了产生panic时重启定时时间,这个值默认情况下是0,即立刻重启系统。所以当panic时没有把kernel信息导入文件的话,那么可能你很难再找到panic产生的地方。

3.3 完整栈跟踪信息的排查方法

栈跟踪信息(stack trace)是排查kernel panic最重要的信息,该信息如果在/var/log/messages日志里当然最好,因为可以看到全部的信息,如果仅仅只是在屏幕上,那么最上面的信息可能因为滚屏消失了,只剩下栈跟踪信息的一部分。如果你有一个完整栈跟踪信息的话,那么就可能根据这些充分的信息来定位panic的根本原因。要确认是否有一个足够的栈跟踪信息,你只要查找包含”EIP”的一行,它显示了是什么函数和模块调用时导致panic。

使用内核调试工具(kenrel debugger ,aka KDB)

如果跟踪信息只有一部分且不足以用来定位问题的根本原因时,kernel debugger(KDB)就需要请出来了。

KDB编译到内核里,panic发生时,他将内核引导到一个shell环境而不是锁定。这样,我们就可以收集一些与panic相关的信息了,这对我们定位问题的根本原因有很大的帮助。

使用KDB需要注意,内核必须是基本核心版本,比如是2.4.18,而不是2.4.18-5这样子的,因为KDB仅对基本核心有效。

4. soft panic

4.1 症状:

没有hard panic严重

通常导致段错误(segmentation fault)

可以看到一个oops信息,/var/log/messages里可以搜索到’Oops’

机器稍微还能用(但是收集信息后,应该重启系统)

4.2 原因

凡是非中断处理引发的模块崩溃都将导致soft panic。在这种情况下,驱动本身会崩溃,但是还不至于让系统出现致命性失败,因为它没有锁定中断处理例程。导致hard panic的原因同样对soft panic也有用(比如在运行时访问一个空指针)

4.3 信息收集

当soft panic发生时,内核将产生一个包含内核符号(kernel symbols)信息的dump数据,这个将记录在/var/log/messages里。为了开始排查故障,可以使用ksymoops工具来把内核符号信息转成有意义的数据。

为了生成ksymoops文件,需要:

从/var/log/messages里找到的堆栈跟踪文本信息保存为一个新文件。确保删除了时间戳(timestamp),否则ksymoops会失败。

运行ksymoops程序(如果没有,请安装)

详细的ksymoops执行用法,可以参考ksymoops(8)手册。

5. Kernel panic实例:

今天就遇到 一个客户机器内核报错:“Kernel panic-not syncing fatal exception”,重启后正常,几个小时后出现同样报错,系统down了,有时重启后可恢复有时重启后仍然报同样的错误。

什么是fatal exception?

“致命异常(fatal exception)表示一种例外情况,这种情况要求导致其发生的程序关闭。通常,异常(exception)可能是任何意想不到的情况(它不仅仅包括程序错误)。致命异常简单地说就是异常不能被妥善处理以至于程序不能继续运行。

软件应用程序通过几个不同的代码层与操作系统及其他应用程序相联系。当异常(exception)在某个代码层发生时,为了查找所有异常处理的代码,各个代码层都会将这个异常发送给下一层,这样就能够处理这种异常。如果在所有层都没有这种异常处理的代码,致命异常(fatal exception)错误信息就会由操作系统显示出来。这个信息可能还包含一些关于该致命异常错误发生位置的秘密信息(比如在程序存储范围中的十六进制的位置)。这些额外的信息对用户而言没有什么价值,但是可以帮助技术支持人员或开发人员调试程序。

当致命异常(fatal exception)发生时,操作系统没有其他的求助方式只能关闭应用程序,并且在有些情况下是关闭操作系统本身。当使用一种特殊的应用程序时,如果反复出现致命异常错误的话,应将这个问题报告给软件供应商。 ” 而且此时键盘无任何反应,必然使用reset键硬重启。

panic.c源文件有个方法,当panic挂起后,指定超时时间,可以重新启动机器,这就是前面说的panic超时重启。如果你的机器事先配置好了魔法键的使用,就可以在超时之前通过魔法键使系统在重启前尽可能多的为你多做些事情,当然这些事情不是用来使系统恢复正常,而是尽量避免损失或导出一些有用信息来帮助后面的定位。

方法:

#vi /etc/sysctl.conf 添加

kernel.panic = 20 #panic error中自动重启,等待timeout为20秒

kernel.sysrq=1 #激活Magic SysRq 否则,键盘鼠标没有响应

按住 [ALT]+[SysRq]+[COMMAND], 这里SysRq是Print SCR键,而COMMAND按以下来解释!

b – 立即重启

e – 发送SIGTERM给init之外的系统进程

o – 关机

s – sync同步所有的文件系统

u – 试图重新挂载文件系统

配置一下以防万一。

很多网友安装linux出现“Kernel panic-not syncing fatal exception in interrupt”是由于网卡驱动原因。解决方法:将选项“Onboard Lan”的选项“Disabled”,重启从光驱启动即可。等安装完系统之后,再进入BIOS将“Onboard Lan”的选项给“enable”,下载相应的网卡驱动安装。

如出现以下报错:

init() r8168 …

… …

… :Kernel panic: Fatal exception

r8168是网卡型号。

在BIOS中禁用网卡,从光驱启动安装系统。再从网上下载网卡驱动安装。

#tar vjxf r8168-8.014.00.tar.bz2

# make clean modules (as root or with sudo)

# make install

# depmod -a

# modprobe r8168

安装好系统后reboot进入BIOS把网卡打开。

另有网友在Kernel panic出错信息中看到“alc880”,这是个声卡类型。尝试着将声卡关闭,重启系统,搞定。

安装linux系统遇到安装完成之后,无法启动系统出现Kernel panic-not syncing fatal exception。很多情况是由于板载声卡、网卡、或是cpu 超线程功能(Hyper-Threading )引起的。这类问题的解决办法就是先查看错误代码中的信息,找到错误所指向的硬件,将其禁用。系统启动后,安装好相应的驱动,再启用该硬件即可。

另外出现“Kernel Panic — not syncing: attempted to kill init”和“Kernel Panic — not syncing: attempted to kill idle task”有时把内存互相换下位置或重新插拔下可以解决问题。

6. 一个kernel panic的解决之法

相信使用linux kernel开发过驱动的兄弟都知道,kernel panic对系统带来的危害要比应用程序panic大的多,甚至可以用灾难来形容。对于应用程序的panic最多导致linux系统杀掉该用户进程,但对于kernel panic就没办法了,因为kernel是整个系统的管理者,自己出现问题了(当然是不可恢复的异常)就只能等待重启了。

kernel panic的最大问题就是难于定位,对于一个开发者来说,有些kernel panic那简直就像是一场噩梦,上面主要说明了如何抓取kernel panic的方法和一些panic实例,当然,抓取panic的打印信息是解决panic的第一步也是关键一步,下面就根据自己曾碰到过的一个kernel panic做为实例来说明从出现panic到解决panic的一般方法。

6.1 抓取kernel panic信息

没错,正如前面说的,这是第一步也是非常关键的一步,如果要解决一个kernel panic当然必须首先要知道它产生的地方,也就是说产生panic的内核函数调用栈,当前的内核调用栈记录了产生kernel panic时的函数调用关系链,这里我不在贴出相关的打印实例,这样的kernel panic网上也到处都是,而且还有很多的文章来说明如何确定是哪个源文件的哪一行导致的panic,因此感兴趣的同学可以搜索一些这样的文章看看,这里指说明一下解决kernel panic的一般步骤和注意事项。

对于抓取kernel log的方法前面有介绍,这里不赘述,但想强调两点:

(1) 不管是什么样的panic,首先要抓取足够的内核打印信息,当然必要的情况下还需要搜集产生kernel panic时的应用程序的打印信息,对于Android系统来说就是logcat信息,在android嵌入式软件平台上其实有更好更全面的log搜集方法,那就是bugreport,它将产生此刻系统全方位的信息,对,没错,就是全方位的信息,包括内核、应用、内存、进程和处理器等所有相关信息,是一个非常好的调试工具,至于bugreport的工作原理感兴趣的同学自己查找下资料。

注意:bugreport的使用需注意两点:第一,它只能在系统正常运行的情况下使用,第二,正因为第一点,你需要在系统产生kernel panic重启系统后的第一时间使用bugreport导出所有信息,因为这所有信息中包含了上次系统重启的原因的相关log信息。

(2) 既然是抓取panic log信息,必然少不了复现panic这个过程,有的panic的产生时概率性随机的,就是说你不知道什么时候就可能会产生panic,因此请珍惜每一次复现panic的机会,起码要在复现panic之前准备好你要抓取的是那些信息,这些信息能否帮助你进一步定位panic,否则,不要在出现panic时手忙脚乱,不知道自己要什么,最好每次复现panic前计划好这次你要那些信息(可能每次抓取信息的重点不一样)。

注意:在工作中经常碰到这样一个现象:测试部门的同学好不容易发现一个问题,请开发同学定位,开发同学基本上没怎么分析问题就嚷着信息抓的不够没法定位,结果让测试同学半天甚至一天来复现这个问题,等复现了问题开发同学还没搞清楚自己到底要什么信息来定位,有的问题复现时的环境只能保持几分钟甚至几十秒钟,这势必会浪费了测试同学的劳动成果。

6.2 分析kernel panic

搜集了足够的panic信息,下面就是分析panic的时候了,对于一个panic问题,你要知道三点:

(1) 首先要对汇编语言有一定的了解,定位panic产生的C代码位置

其实就是根据当前内核线程的内核调用栈查找产生panic调用链,在panic log的前面几行已经显示了kernel panic的代码位置,但这个位置是相对于产生panic函数的偏移,你并不知道它到底是哪一行,这个时候你需要objdump反汇编器来对那个产生panic的镜像文件反汇编,然后根据panic信息的指示找到对应的汇编代码,对照C代码根据汇编上下文确定C代码行,其实,kernel panic的产生一般都是非法地址的引用,尤其是NULL指针的引用,这也比较容易定位出panic的C代码行。

(2) 分析导致panic的C代码行上下文,确定panic引入点

第一步应该会比较容易找到导致panic 的C代码行,根据产生panic的代码进一步找到panic的引入点,这一步可以搭配printk来定位(如果是大概率panic就更容易定位了),这一步相对第一步花费多一点的时间,如果是应用代码分析到这里已经差不多结束了,确定了panic引入点就可以修改代码进行回归测试了,但对于kernel来说要复杂的多。

正如之前曾碰到的panic,复现虽然不容易但是基本上在固定时间点左右就可以复现,我是用的脚本循环加载卸载wifi模块,每次都是大约500次左右产生panic,要知道必现的panic就容易解决的多了,但当时因为这500次的循环就要花费2个小时左右,而且环境还经常出现问题,导致我花费很长时间才定位出问题所在:每次的加载和卸载wifi模块都导致devices kset节点引用计数多减一,当devices kset的引用计数变为0的时候被系统回收,linux系统随后可能会出现N种panic现象,之后发现是因为wifi模块每次加载下载时对应的设备节点的引用计数增减失衡导致devices kset被多减一,然后发现是linux 内核核心代码的问题。

(3) 最好不要怀疑linux的核心代码,也不要试图去修改

正因为这一点,让我迟迟不敢确定是不是真的核心代码问题,linux的核心代码那可是数以万计的大牛经过千锤百炼的代码,岂容你轻易修改,经过进一步的分析这个panic是因为我们用的wifi卡是非标准媒体卡,走的是非标准流程,在这个流程中对wifi设备初始化时少了一次wifi设备节点的引用,但在卸载模块时同标准卡一样被解引用了。

(4)不要坚定的以为围绕着panic信息就能解决panic问题

还是上面的panic,实际上,上面提到的panic问题其实应该是很多的panic,这也是在后期复现panic时发现的,在加载卸载500次左右时必现panic,但却不是同一个panic,如果按照正常思路:既然是panic,就应该从panic信息下手,顺藤摸瓜一直追下去。如果是这样,这个问题恐怕永远也解决不了,因为你在复现一个panic时总是会有其他的panic出现,这回让你无所适从的。

通过对这些panic的log的分析,发现他们都有一个共性,在产生panic之前都有一段WARNING打印,也正是对这段打印的分析找出了问题的根源,对于这段WARNING的内容和分析过程不在这里说明,只为表达下面的观点:

事实证明,在碰到panic问题定位时,如果想当一段时间内定位不出来,又没有什么更好的思路时,你应该回头看看在panic之前kernel是否产生了哪些不太正常的log,这也许就是导致kernel panic的前兆或推手。

(5) 尽可能多的把握linux kernel的行为,对一些难啃的panic大胆猜测

这里的大胆猜测是建立在想当了解linux kernel行为上的有理性的推理,尽管有些猜测并不是完全正确的,但在你证明它是正确的过程中或许会有意外收获。对于wifi模块加载卸载的panic问题来说,我曾有过两次错误的猜测:

第一次,因为长时间的加载卸载都会出现panic,而且开始发现的panic是在kmem_cache_alloc函数中,因此猜测是内存泄露导致的内存耗尽,因此在后面的复现过程中我写了个脚本循环打印内存的使用情况,发现内存的占用一直稳定在一个正常的范围,证明了我的第一个猜测是错误的。

第二次,在看到devices 的内核对象kobject的名字在panic之前出现乱码的情况下(printk打印了名字),我曾大胆地做过猜测:linux kernel发生了踩内存现象,导致devices kset对象被破坏。随后做了各方面的努力来证明我的想法,结果发现几乎都是在第493次加载wifi模块时出现的panic问题,这让我很迷惑,如果是踩内存怎么可能固定在493次发生,虽然不能完全证明这个猜想是错误的,但这足以说明我的方向有问题。

如此反反复复,花费了我两个星期的时间才搞定这个panic,因此,kernel panic虽然难啃,但只要你愿意去尝试愿意去努力,就算最后拿不下这个panic,你也会学到很多很多的东西,包括linux kernel行为,这些会对你以后的学习产生很大的影响,在碰到这类问题一定是信心满满的。

7. 小结

一直想总结一点kernel panic的解决之法,在网上也搜索了很多资料,基本上都一样,本文前面也引用了这些文章中的一篇,曾经做过的总结过的东西能记录下来给别人看和给以后自己复习都是很有意义的事情,以前kernel panic的问题总让我不敢靠的太近,现在我还是可以比较自信的面对他们,这里也只是给同学们一些解决panic的建议,个人觉得分析一个具体的实例的意义也不是太大,所以也没有对一个具体的实例做详细分析,希望可以找到更多的相关文章来拜读,夜已深沉,还有什么人...

我是新手,请问什么是内核,干嘛用的?

内核是操作系统最基本的部分。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件,这种访问是有限的,并且内核决定一个程序在什么时候对某部分硬件操作多长时间。直接对硬件操作是非常复杂的,所以内核通常提供一种硬件抽象的方法来完成这些操作。硬件抽象隐藏了复杂性,为应用软件和硬件提供了一套简洁,统一的接口,使程序设计更为简单。

严格地说,内核并不是计算机系统中必要的组成部分。程序可以直接地被调入计算机中执行,这样的设计说明了设计者不希望提供任何硬件抽象和操作系统的支持,它常见于早期计算机系统的设计中。最终,一些辅助性程序,例如程序加载器和调试器,被设计到机器核心当中,或者固化在只读存储器里。这些变化发生时,操作系统内核的概念就渐渐明晰起来了。

一个更重要的问题是,什么人才要了解内核。或者说,对内核的了解程度,会怎样影响一个人的工作,毕竟,它是复杂的。

[编辑本段]内核分类

单内核 它为潜在的硬件提供了大量完善的硬件抽象操作。

微内核 只提供了很小一部分的硬件抽象,大部分功能由一种特殊的用户态程序:服务器来完成。

混合内核 它很像微内核结构,只不过它的的组件更多的在核心态中运行,以获得更快的执行速度。

外内核 这种内核不提供任何硬件抽象操作,但是允许为内核增加额外的运行库,通过这些运行库应用程序可以直接地或者接近直接地对硬件进行操作。

单内核

单内核结构在硬件之上定义了一个高阶的抽象界面,应用一组原语(或者叫系统调用)来实现操作系统的功能,例如进程管理,文件系统,和存储管理等等,这些功能由多个运行在核心态的模块来完成。

尽管每一个模块都是单独地服务这些操作,内核代码是高度集成的,而且难以编写正确。因为所有的模块都在同一个内核空间上运行,一个很小的bug都会使整个系统崩溃。然而,如果开发顺利,单内核结构就可以从运行效率上得到好处。

很多现代的单内核结构内核,如Linux和FreeBSD内核,能够在运行时将模块调入执行,这就可以使扩充内核的功能变得更简单,也可以使内核的核心部分变得更简洁。

单内核结构的例子:

1.传统的UNIX内核,例如伯克利大学发行的版本

2.Linux内核

微内核

微内核结构由一个非常简单的硬件抽象层和一组比较关键的原语或系统调用组成,这些原语仅仅包括了建立一个系统必需的几个部分,如 线程管理,地址空间和进程间通信等。

微核的目标是将系统服务的实现和系统的基本操作规则分离开来。例如,进程的输入/输出锁定服务可以由运行在微核之外的一个服务组件来提供。这些非常模块化的用户态服务器用于完成操作系统中比较高级的操作,这样的设计使内核中最核心的部分的设计更简单。一个服务组件的失效并不会导致整个系统的崩溃,内核需要做的,仅仅是重新启动这个组件,而不必影响其它的部分

微内核将许多OS服务放入分离的进程,如文件系统,设备驱动程序,而进程通过消息传递调用OS服务.微内核结构必然是多线程的,第一代微内核,在核心提供了较多的服务,因此被称为'胖微内核',它的典型代表是MACH,它既是GNU HURD也是APPLE SERVER OS 的核心,可以说,蒸蒸日上.第二代为微内核只提供最基本的OS服务,典型的OS是QNX,QNX在理论界很有名,被认为是一种先进的OS.

微内核的例子:

1.AIX

2.BeOS

3.L4微内核系列

4.Mach, 用于GNU Hurd和Mac OS X

5.Minix

6.MorphOS

7.QNX

8.RadiOS

9.VSTa

单内核与微内核的比较

单内核结构是非常有吸引力的一种设计,由于在同一个地址空间上实现所有低级操作的系统控制代码的复杂性的效率会比在不同地址空间上实现更高些。

20世纪90年代初,单内核结构被认为是过时的。把Linux设计成为单内核结构而不是微内核引起了无数的争议。

现在,单核结构正趋向于容易被正确设计,所以它的发展会比微内核结构更迅速些。两个阵营中都有成功的案例。微核经常被用于机器人和医疗器械的嵌入式设计中,因为它的系统的关键部分都处在相互分开的,被保护的存储空间中。这对于单核设计来说是不可能的,就算它采用了运行时加载模块的方式。

尽管Mach是众所周知的多用途的微内核,人们还是开发了除此之外的几个微内核。L3是一个演示性的内核,只是为了证明微内核设计并不总是低运行速度。它的后续版本L4甚至可以将Linux内核在单独的地址空间作为它的一个进程来运行。

QNX是一个从20世纪80年代就开始设计的微内核系统。它比Mach更接近微内核的理念。它被用于一些特殊的领域,在这些情况下由于软件错误导致系统失效是不允许的。例如航天飞机上的机械手,还有研磨望远镜镜片的机器,一点点失误就会导致上千美元的损失。

很多人相信,由于Mach不能够解决一些提出微内核理论时针对的问题,所以微内核技术毫无用处。Mach的爱好者表明这是非常狭隘的观点,遗憾的是似乎所有人都开始接受这种观点。

混合内核

混合内核实质上是微内核,只不过它让一些微核结构运行在用户空间的代码运行在内核空间,这样让内核的运行效率更高些。这是一种妥协做法,设计者参考了微内核结构的系统运行速度不佳的理论。然而后来的实验证明,纯微内核的系统实际上也可以是高效率的。大多数现代操作系统遵循这种设计范畴,微软视窗就是一个很好的例子。另外还有XNU,运行在苹果Mac OS X上的内核,也是一个混合内核。

混合内核的例子:

BeOS 内核

DragonFly BSD

ReactOS 内核

Windows NT、Windows 2000、Windows XP、Windows Server 2003以及Windows Vista等基于NT技术的操作系统

XNU

一些人认为可以在运行时加载模块的单核系统和混合内核系统没有区别。这是不正确的。混合意味着它从单核和微核系统中都吸取了一定的设计模式,例如一些非关键的代码在用户空间运行,另一些在内核空间运行,单纯是为了效率的原因。

外内核

外内核系统,也被称为纵向结构操作系统,使一种比较极端的设计方法。

它的设计理念是让用户程序的设计者来决定硬件接口的设计。外内核本身非常的小,它通常只负责系统保护和系统资源复用相关的服务。

传统的内核设计(包括单核和微核)都对硬件作了抽象,把硬件资源或设备驱动程序都隐藏在硬件抽象层下。比方说,在这些系统中,如果分配一段物理存储,应用程序并不知道它的实际位置。

而外核的目标就是让应用程序直接请求一块特定的物理空间,一块特定的磁盘块等等。系统本身只保证被请求的资源当前是空闲的,应用程序就允许直接存取它。既然外核系统只提供了比较低级的硬件操作,而没有像其他系统一样提供高级的硬件抽象,那么就需要增加额外的运行库支持。这些运行库运行在外核之上,给用户程序提供了完整的功能。

理论上,这种设计可以让各种操作系统运行在一个外核之上,如Windows和Unix。并且设计人员可以根据运行效率调整系统的各部分功能。

现在,外核设计还停留在研究阶段,没有任何一个商业系统采用了这种设计。几种概念上的操作系统正在被开发,如剑桥大学的Nemesis,格拉斯哥大学的Citrix系统和瑞士计算机科学院的一套系统。麻省理工学院也在进行着这类研究。

[编辑本段]无核

TUNES Project和UnununiumOS都进行无内核的尝试. 无内核的系统is not limited to a single centralizing entry point.

[编辑本段]参考

操作系统

[编辑本段]内核发展中的改进

红旗5就是2.6内核了,期待中

转:期待已久的2.6内核终于到来了。IBMLinuxTechnologyCenter的PaulLarson暗中关注那些让2.6成为有史以来最好内核的工具、测试和技术——从修正控制和回归测试到缺陷追踪和列表保持。

经过为期三年的积极开发,新2.6Linux内核最近已经发布了,在这期间,Linux内核的开发和测试方法发生了一些有趣的变化。当前,开发内核的方法在很多方面与三年前没什么不同。不过,一些关键变化已经使整体的稳定性和质量得到了提高。

源代码管理

历史上,从来没有出现过用于Linux内核的正式的源代码管理或修正控制系统。实际上,很多开发者实现了他们自己的修正控制器,但是并没有官方的LinuxCVS档案库,让LinusTorvalds检查加入代码,并让其他人可以由此获得代码。修正控制器的缺乏,常常会使发行版本之间存在“代沟”,没有人真正知道加入了哪些改变,这些改变是否能很好地融合,或者在即将发行的版本中哪些新内容是值得期待的。通常,如果更多的开发者可以像了解他们自己所做的改变一样了解到那些变化,某些问题就可以得到避免。

由于缺乏正式的修正控制器和源代码管理工具,使得很多人提议使用一个名为BitKeeper的产品。BitKeeper是一个源代码控制管理系统,很多内核开发者已经成功地将其应用于他们自己的内核开发工作中。最初的2.5内核发布后不久,LinusTorvalds开始试用BitKeeper,以确定它是否能满足他的需要。现在,主要的2.4和2.5内核的Linux内核源代码都是用BitKeeper来管理的。对大部分可能很少或者根本不关心内核开发的用户来说,这一点看起来可能无关紧要。不过,在一些情况下,用户可以受益于那些由于使用BitKeeper而带来的开发Linux内核的方法的改变。

使用BitKeeper的最大好处之一是补丁的融合。当多个补丁应用于同一基础的代码之上,并且其中一些补丁会对同一部分产生影响时,就可能会出现融合问题。一个好的源代码管理系统可以自动地完成其中一些更为复杂的部分工作,这样可以更快地融合补丁,并使更多的补丁加入到内核中。随着Linux内核开发者社区的扩大,非常需要修正控制器来帮助保持对所有改变的追踪。由于每个人都可以将这些改变集成到主要的Linux内核中,为保证补丁不会被遗忘并可以方便地融合和管理,BitKeeper等工具是必不可少的。

非常有必要使用一个实时的、集中的档案库来保存对Linux内核的最新更新。每一个被内核接受的改变或者补丁都被作为一个改变集被追踪。终端用户和开发者可以保存他们自己的源文件档案库,并根据需要可以通过一个简单的命令用最新的改变集进行更新。对开发者来说,这意味着可以始终使用最新的代码拷贝。测试人员可以使用这些逻辑的改变集合来确定哪些变化导致了问题的产生,缩短调试所需要的时间。甚至那些希望使用最新内核的用户也可以直接利用实时的、集中的档案库,因为现在一旦他们所需要的部件或缺陷修复加入到内核中,他们就可以马上进行更新。当代码融合到内核时,任何用户都可以提供关于这些代码的即时反馈和缺陷报告。

并行开发

随着Linux内核的成长,变得更加复杂,而且吸引更多开发者将注意力集中到内核的特定方面的专门开发上来,出现了另一个开发Linux方法的有趣改变。在2.3内核版本的开发期间,除了由LinusTorvalds发行的主要的一个内核树之外,还有一些其他的内核树。

在2.5的开发期间,内核树出现了爆炸式的增长。由于使用源代码管理工具可以保持开发的同步并行进行,这样就可能实现开发的部分并行化。为了让其他人在他们所做的改变被接受之前可以进行测试,有一些开发需要并行化。那些保持自己的树的内核维护者致力于特定的组件和目标,比如内存管理、NUMA部件、改进扩展性和用于特定体系结构的代码,还有一些树收集并追踪对许多小缺陷的纠正。

图1.Linux2.5开发树

这种并行开发模型的优点是,它使得需要进行重大改变的开发者,或者针对一个特定的目标进行大量类似改变的那些开发者可以自由地在一个受控环境中开发,而并不影响其他人所用内核的稳定性。当开发者完成工作后,他们可以发布针对Linux内核当前版本的补丁,以实现到此为止他们所完成的改变。这样,社区中的测试人员就可以方便地测试这些改变并提供反馈。当每一部分都被证明是稳定的之后,那些部分可以单独地,或者甚至同时全部地,融合到主要Linux内核中。

在实际应用中测试

过去,Linux内核测试方法围绕开放源代码开发模型进行。由于代码一经发布后就公开给其他开发者进行审查,因此从来没有出现过一个与其他形式的软件开发类似的正式的验证周期。这种方法背后的理论依据是“TheCathedralandtheBazaar”中所谓的“Linus法则”(请查阅参考资料以获得相关的参考),这一法则的内容为“众人的眼光是雪亮的”。换句话说,高力度的审查可以找出大部分真正的大问题。

然而实际上,内核有很多复杂的相互联系。即使进行了足够力度的审查,还是会漏过很多严重的缺陷。此外,最新的内核一经发布,终端用户可以(也经常是)下载并使用。2.4.0发布时,社区中很多人都提议进行更有组织的测试,以保证特定测试和代码审查的强度。有组织的测试包括运用测试计划、测试过程中的可重复性等等。使用所有的三种方法比最初只使用两种方法会带来更高的代码质量。

Linux测试项目

最早对Linux开始进行有组织测试的贡献者是Linux测试项目(LinuxTestProject,LTP)。这个项目的目的是通过更有组织的测试方法提高Linux的质量。这个测试项目的一部分是自动测试套件的开发。LTP开发的主要测试套件也叫做Linux测试项目。2.4.0内核发布时,LTP测试套件只有大约100个测试。随着2.4和2.5版本Linux的发展与成熟,LTP测试套件也正在发展和成熟。当前,Linux测试项目包括超过2000个测试,而且这个数字还在增长!

代码覆盖分析

现在所使用的新工具为内核提供了代码覆盖分析的功能。覆盖分析告诉我们,在一个给定的测试运行时,内核中哪些行代码被执行。更重要的是,覆盖分析提示了内核的哪些部分还根本没有被测试到。这个数据是重要的,因为它指出了需要再编写哪些新测试来测试内核的那些部分,以使内核可以得到更完备的测试。

持续多日的内核回归测试

在2.5的开发周期中,Linux测试项目所采用的另一个项目是,用LTP测试套件对Linux内核执行持续多日的回归测试。人们用BitKeeper创建了一个实时的、集中的档案库,以随时可以获得Linux内核的快照。在没有使用BitKeeper和快照时,测试人员不得不等到内核发布后才可以开始测试。现在,内核只要发生了改变,测试人员就可以进行测试。

使用自动化工具来执行持续多日的回归测试的另一个优点是,和上一次测试相比变化较小。如果发现了一个新的回归缺陷,通常会容易地检测出这个缺陷可能是哪个改变导致的。

同样,由于是最新的改变,因此它在开发者的脑海中印象还比较深——希望这能让他们更容易地记起并修订相应的代码。或许Linus法则应该有这样一个结论,有一些缺陷比其他缺陷更容易被发现,因为那些正是持续多日的内核回归测试所发现并处理的那些。在开发周期中和实际发布之前能够每天进行这些测试,这就使那些只关注完整发行版本的测试者可以将精力集中于更严重和耗时的缺陷。

可扩展测试平台

另外一个名为开放源代码开发实验室(OpenSourceDevelopmentLabs,OSDL)的团队也为Linux测试做出了重要的贡献。2.4内核发布后不久,OSDL创建了一个叫做可扩展测试平台(ScalableTestPlatform,STP)的系统。STP是一个自动化的测试平台,让开发者和测试者可以运行OSDL硬件之上的系统所提供的测试。开发者甚至可以使用这个系统来测试他们自己的针对内核的补丁。可扩展测试平台简化了测试的步骤,因为STP可以构建内核、设置测试、运行测试,并收集结果。然后得到结果以进行深入地比较。很多人无法接触大型系统,比如具有8个处理器的SMP机器,而通过STP,任何人都可以在像这样的大型系统上运行测试,这个系统(STP)的另一个好处就在于此。

追踪缺陷

自从2.4发布以来,对Linux内核的有组织测试最大的改进之一是缺陷追踪。过去,在Linux内核中发现的缺陷会报告给Linux内核邮件列表,报告给特定组件或者特定体系的邮件列表,或者直接报告给维护发现缺陷的那部分代码的个人。随着开发和测试Linux的人数的增加,这个系统的不足之处很快就暴露了出来。在以前,除非人们对缺陷的报告可以惊人地维持下去,缺陷经常被遗漏、遗忘或者忽略。

现在,OSDL安装了一个缺陷追踪系统(请参阅参考资料中的链接),来报告和追踪Linux内核的缺陷。系统经过了配置,这样当某个组件的缺陷被报告时,那个组件的维护者就会得到通知。维护者既可以接受并修复那个缺陷,或重新指定缺陷(如果最终确定实际上那是内核另外一部分的缺陷),也可以排除它(如果最终确定并不是真正的缺陷,比如错误配置的系统)。报告给邮件列表的缺陷还有丢失的危险,因为越来越多的电子邮件涌向那个列表。然而,在缺陷追踪系统中,始终有对每一个缺陷及其当前状态的记录。

大量信息

在为将来的2.6Linux内核进行开的过程中,除了这些自动化的信息管理方法之外,开放源代码社区的不同成员还收集和追踪了数量惊人的信息。

例如,在KernelNewbies站点上创建了一个状态列表,来保持对已经提出的内核新部件的追踪。这个列表包含了以状态排序的条目,如果它们已经完成了,则说明它们已经包含在哪个内核中,如果还没有完成,则指出还需要多长时间。列表上很多条目的链接指向大型项目的Web站点,或者当条目较小时,链接指向一个解释相应部件的电子邮件信息的拷贝。

内核版本历史

到现在我们很多人已经熟悉了Linux内核的版本编号系统,不过AndriesBrouwer提醒了我们实际上它是如何不规则的。

Linux的第一个公开版本是1991年10月的0.02版本。两个月以后,在1991年12月,Linus发布了0.11版本,这是第一个可以不依赖于Minix就可以使用的独立内核。

0.12版本发布一个月以后,在3月,版本号跳到了0.95,反映出系统正变得成熟。不仅如此,直到两年后,也就是1994年3月,具有里程碑意义的1.0.0才完成。

大约从这时起开始使用两“路”编号方法标注内核的开发。偶数号的内核(比如1.0、2.2、2.4,现在是2.6)是稳定的,“产品”型号。同时,奇数号的内核版本(1.1、2.3)是前沿的或者“发展中的”内核。直接最近,一个稳定的内核发布以后几个月就开始新内核的开发工作。然而,2.5的开发工作是在2.4完成后几ten个月以后才开始的。

那么我们什么时候可以期待2.7呢?这不好说,不过在KernelTrap已经有了一个讨论的头绪。

在那之前,您可以阅读RagibHasan的文章以深入了解Linux的历史。

同时,“post-halloween文档”告诉用户即将到来的2.6内核有哪些可期待的东西(参阅参考资料中的链接)。post-halloween文档的大部分讨论内容是用户需要注意的主要改变,以及需要更新的系统工具(为了利用它们)。关心这一信息人的主要是那些期望提前了解2.6内核中有哪些内容的Linux发行商,还有终端用户,这可以让他们确定为了能利用新部件是否有需要升级的程序。

KernelJanitors项目保持了(实际上现在还在保持)一个列表,内容是需要修复的较小缺陷和解决方法。这些缺陷解决方法中大部分是由于向内核打较大的补丁时需要改动很多部分代码而导致的,比如有些地方会影响设备驱动程序。那些新近从事内核开发的人开始时的工作可以选择列表中的条目,这样让他们可以通过小项目学习如何编写内核代码,同时有机会为社区做出贡献。

还有,在另一个预发布的项目中,JohnCherry追踪了在对每个已经发布的内核版本进行编译时发现的错误和警告。这些编译统计数字随着时间的流逝一直持续下降,而且,以系统的形式来发布这些结果使得所取得的进展一目了然。在很多情况下,可以像使用KernelJanitors列表一样来利用这些警告和错误消息中的一部分,因为编译错误通常是由小的缺陷引起的,需要一些努力去修复。

最后,还有AndrewMorton的“must-fix”列表。由于他已经被选定为2.6内核发布后的维护者,他运用他的特权概括地列出了那些他认为在最终的2.6内核发布前最迫切需要解决方案的问题。must-fix列表中包含了内核Bugzilla系统中的缺陷,需要完成的部件,以及其他已知的问题,这些问题如不解决将阻碍2.6发布。这一信息可以帮助指明在新内核发布前还需要哪些步骤;对那些关心这一万众期待的2.6内核发布何时能完成的人来说,它还可以提供有价值的信息。

自从去年年底2.6内核发布以后,这些资料中有一些已经明显不再进行维护了。其他的相关工作在主要版本发布后仍未结束,还要继续进行后期的更新。有趣的是能看到哪些又被重新提起,有了哪些革新,我们又一次接近了一个主要发布版本。

结束语

多数人在考虑内核的一个新的稳定版本时,第一个问题通常是“这一版本中有什么新东西吗?”实际上除了一些新特性和修复之外,在幕后还有一个随着时间而不断改进的过程。

在Linux社区中,开放源代码开发日益兴旺。致力于Linux内核和其他方面工作的编码者之间联系是松散的,这就使得团队可以成功地适应变化。在许多方面,相对于已经完成的很多单个的改进和缺陷修复而言,Linux的开发和测试方法——尤其是这些方法随时间的推移得到了改进——对新内核的可靠性影响更为深远。

[编辑本段]天文学意义上的内核

从天文学意义上讲,一颗行星(或一颗恒星)都有两个核:内核和外核,星体内核的温度可高达几千摄氏度。

Kernel LDA是监督学习方法还是非监督学习方法

1、机器学习按照方法来分类,可以分成四类,分别是:监督学习、无监督学习、半监督学习和强化学习。

2、监督学习针对有标签数据集,它通过学习出一个模型(其实就是一个函数)来拟合数据,按照模型(函数)的输出结果是否离散又可以分为两类,分别是:(1)输出结果为离散值,则为分类问题(常见的分类算法:KNN、贝叶斯分类器、决策树、SVM、神经网络、GBDT、随机森林等);(2)输出结果为连续值,则为回归问题(有线性回归和逻辑回归两种)。

3、无监督学习针对没有标签的数据集,它将样本按照距离划分成类簇,使得类内相似性最大,类间相似性最小。通过观察聚类结果,我们可以得到数据集的分布情况,为进一步分析提供支撑。常见的聚类算法有K-means、高斯混合模型和LDA。

什么是 核方法 kernal 通俗

核方法kernel methods (KMs)是一类模式识别的算法。其目的是找出并学习一组数据中的相互的关系。用途较广的核方法有支持向量机、高斯过程等。

核方法是解决非线性模式分析问题的一种有效途径,其核心思想是:首先,通过某种非线性映射将原始数据嵌入到合适的高维特征空间;然后,利用通用的线性学习器在这个新的空间中分析和处理模式。

相对于使用通用非线性学习器直接在原始数据上进行分析的范式,核方法有明显的优势:

首先,通用非线性学习器不便反应具体应用问题的特性,而核方法的非线性映射由于面向具体应用问题设计而便于集成问题相关的先验知识。

再者,线性学习器相对于非线性学习器有更好的过拟合控制从而可以更好地保证泛化性能。

还有,很重要的一点是核方法还是实现高效计算的途径,它能利用核函数将非线性映射隐含在线性学习器中进行同步计算,使得计算复杂度与高维特征空间的维数无关。

核方法kernel methods (KMs)是一类模式识别的算法。其目的是找出并学习一组数据中的相互的关系。用途较广的核方法有支持向量机、高斯过程等。

--------------

本文对核方法(kernel method)进行简要的介绍。

核方法的主要思想是基于这样一个假设:“在低维空间中不能线性分割的点集,通过转化为高维空间中的点集时,很有可能变为线性可分的” ,例如下图

左图的两类数据要想在一维空间上线性分开是不可能的,然而通过F(x)=(x-a)(x-b)把一维空间上的点转化为右图上的二维空间上,就是可以线性分割的了。

然而,如果直接把低维度的数据转化到高维度的空间中,然后再去寻找线性分割平面,会遇到两个大问题,一是由于是在高维度空间中计算,导致curse of dimension问题;二是非常的麻烦,每一个点都必须先转换到高维度空间,然后求取分割平面的参数等等;怎么解决这些问题?答案是通过核戏法(kernel trick)。

(pku, shinningmonster, sewm)

Kernel Trick: 定义一个核函数K(x1,x2) = \phi(x1), \phi(x2), 其中x1和x2是低维度空间中点(在这里可以是标量,也可以是向量),\phi(xi)是低维度空间的点xi转化为高维度空间中的点的表示, , 表示向量的内积。

这里核函数K(x1,x2)的表达方式一般都不会显式地写为内积的形式,即我们不关心高维度空间的形式。核函数巧妙地解决了上述的问题,在高维度中向量的内积通过低维度的点的核函数就可以计算了。这种技巧被称为Kernel trick。这里还有一个问题:“为什么我们要关心向量的内积?”,一般地,我们可以把分类(或者回归)的问题分为两类:参数学习的形式和基于实例的学习形式。

参数学习的形式就是通过一堆训练数据,把相应模型的参数给学习出来,然后训练数据就没有用了,对于新的数据,用学习出来的参数即可以得到相应的结论;

而基于实例的学习(又叫基于内存的学习)则是在预测的时候也会使用训练数据,如KNN算法。而基于实例的学习一般就需要判定两个点之间的相似程度,一般就通过向量的内积来表达。从这里可以看出,核方法不是万能的,它一般只针对基于实例的学习。

紧接着,我们还需要解决一个问题,即核函数的存在性判断和如何构造? 既然我们不关心高维度空间的表达形式,那么怎么才能判断一个函数是否是核函数呢?

Mercer 定理:任何半正定的函数都可以作为核函数。所谓半正定的函数f(xi,xj),是指拥有训练数据集合(x1,x2,...xn),我们定义一个矩阵的元素aij = f(xi,xj),这个矩阵式n*n的,如果这个矩阵是半正定的,那么f(xi,xj)就称为半正定的函数。这个mercer定理不是核函数必要条件,只是一个充分条件,即还有不满足mercer定理的函数也可以是核函数。常见的核函数有高斯核,多项式核等等,在这些常见核的基础上,通过核函数的性质(如对称性等)可以进一步构造出新的核函数。SVM是目前核方法应用的经典模型。

上述是目前我所理解到的核方法的主要精神。

(责任编辑:IT教学网)

更多

相关心得技巧文章