01.序言
本文主要讲解哪些是Linux内核,以及通过多张图片展示Linux内核的作用与功能,以以便读者能快速理解哪些是Linux内核,能读懂Linux内核。
拥有超过1300万行的代码,Linux内核是世界上最大的开源项目之一,而且内核是哪些,它用于哪些?
02.哪些是内核
内核是与计算机硬件插口的易替换软件的最低级别。它负责将所有以“用户模式”运行的应用程序联接到化学硬件,并容许称为服务器的进程使用进程间通讯(IPC)彼此获取信息。
03.内核还要分种类?是的,没错。3.1微内核
微内核只管理它必须管理的东西:CPU、内存和IPC。计算机中几乎所有的东西都可以被看作是一个附件,而且可以在用户模式下处理。微内核具有可移植性的优势,由于只要操作系统一直企图以相同的方法访问硬件,就毋须害怕您是否修改了视频卡,甚至是操作系统。微内核对显存和安装空间的占用也十分小,但是它们常常更安全,由于只有特定的进程在用户模式下运行,而用户模式不具有管理员模式的高权限。
3.1.1Pros3.1.2Cons3.2单内核
单内核与微内核相反,由于它们除了包含CPU、内存和IPC,并且还包含设备驱动程序、文件系统管理和系统服务器调用等内容。单内核更擅长于访问硬件和多任务处理,由于假如一个程序须要从显存或运行中的其他进程中获取信息,这么它就有一条更直接的线路来访问信息,而不须要在队列中等待来完成任务。并且,这可能会造成问题,由于在管理模式下运行的东西越多,假如行为不正常,都会有越多的东西造成系统崩溃。
3.2.1Pros3.2.2Cons
04.混和的内核
混和内核才能选择在用户模式下运行哪些,以及在管理模式下运行哪些。一般情况下,设备驱动程序和文件系统I/O将在用户模式下运行,而IPC和服务器调用将保持在管理器模式下。这是两全其美,但一般须要硬件制造商做更多的工作,由于所有驱动程序的责任都由她们来承当。它还可能存在一些与微内核固有的延后问题。
4.1Pros4.2Cons05.Linux内核文件在那里
Ubuntu中的内核文件储存在/boot文件夹中,称为vmlinux-version。vmlinuz这个名子来自于unix世界,早在60年代,她们就把内核简单地称为“unix”,所以当内核在90年代首次开发时,Linux就开始把内核称为“Linux”。
当开发虚拟显存便于更容易地进行多任务处理时,将“vm”放在文件的后面,以显示内核支持虚拟显存。有一段时间,Linux内核被称为vmlinux,而且内核显得太大linux内核驱动api手册,难以放入可用的引导显存,因而压缩了内核映像,并将末尾的x修改为z,以显示它是用zlib压缩的。并不总是使用相同的压缩,一般用LZMA或BZIP2替换,一些内核简单地称为zImage。
版本号将采用A.B.C.格式D在。B可能是2.6,C是您的版本,D表示您的补丁或补丁。
在/boot文件夹中还有其他特别重要的文件,称为initrd.img-version、system.map-version,config-version。initrd文件用作一个小RAMc盘,用于提取和执行实际的内核文件。这个系统。map文件用于内核完全加载之前的显存管理,配置文件告诉内核在编译内核映像时要加载什么选项和模块。
06.Linux内核体系结构
由于Linux内核是单片的,所以它比其他类型的内核占用空间最大,复杂度也最高。这是一个设计特点,在Linux初期造成了相当多的争辩,但是依然带有一些与单内核固有的相同的设计缺陷。
为了解决这种缺陷,Linux内核开发人员所做的一件事就是使内核模块可以在运行时加载和卸载,这意味着您可以动态地添加或删掉内核的特点。这除了可以向内核添加硬件功能,还可以包括运行服务器进程的模块,例如低级别虚拟化,但也可以替换整个内核,而不须要在个别情况下重启计算机。
想像一下,假若您可以升级到Windows服务包,而不须要重新启动……
07.内核模块
假如Windows早已安装了所有可用的驱动程序,而您只须要打开所需的驱动程序怎样办?这本质上就是内核模块为Linux所做的。内核模块,亦称为可加载内核模块(LKM),对于保持内核在不消耗所有可用显存的情况下与所有硬件一起工作是必不可少的。
模块一般向基本内核添加设备、文件系统和系统调用等功能。lkm的文件扩充名是.ko,一般储存在/lib/modules目录中。因为模块的特点,您可以通过在启动时使用menuconfig命令将模块设置为load或notload,或则通过编辑/boot/config文件,或则使用modprobe命令动态地加载和卸载模块,轻松订制内核。
第三方和封闭源码模块在一些发行版中是可用的,例如Ubuntu,默认情况下可能难以安装,由于这种模块的源代码是不可用的。该软件的开发人员(即nVidia、ATI等)不提供源代码,而是建立自己的模块并编译所需的.ko文件便于分发。其实这种模块像beer一样是免费的,但它们不像speech那样是免费的,因而不包括在一些发行版中,由于维护人员觉得它通过提供非免费软件“污染”了内核。
内核并不神奇,但对于任何正常运行的计算机来说,它都是必不可少的。Linux内核不同于OSX和Windows,由于它包含内核级别的驱动程序嵌入式linux 培训,并使许多东西“开箱即用”。希望您能对软件和硬件怎么协同工作以及启动计算机所需的文件有更多的了解。
08.Linux内核学习经验总结
开篇
学习内核,每位人都有自己的学习方式,仁者见仁智者见智。以下是我在学习过程中总结下来的东西,对自身来说,我觉得比较有效率,掏出来跟你们交流一下。
内核学习,一偏之见;疏忽难免,请求见谅。
为何写这篇博客
刚开始学内核的时侯,不要执著于一个方面,不要专注于一个子系统就一头扎到实际的代码行中去,由于这样的话,牵连的面会很广,会遇到好多困难,容易形成挫败感,一个函数体中(假定刚开始的时侯正在学习某个方面的某个具体的功能函数)很可能参杂着其他各个子系统方面设计理念(多是大量相关的数据结构或则全局变量,用于支撑该子系统的管理工作)下相应的代码实现,这个时侯见到这种东西,错综芜杂,是没有头绪并且很不理解的,会形成好多好多的疑惑,(这个时侯假如对这种疑惑纠缠不清,刨根问底,这么事实上就是在学习当前子系统的过程中频繁的去进军其他子系统,这时侯注意力就分散了),而事实上等了解了各个子系统后再回头看那些东西的话,就简单多了,但是思路也会比较清晰。所以,要防止“只见行道树,不见森林”,不要急于深入到底层代码中去,不要过早研究底层代码。
我在大二的时侯刚开始接触内核,就犯了这个错误,一头扎到显存管理里头,去看特别底层的实现代码,尽管也是构建在显存管理的设计思想的基础上,并且相对来说,比较孤立,由于此时并没有学习其它子系统,应当说无论是视野还是思想,都比较自私,所以代码中牵扯到的其它子系统的实现我都直接跳过了,这一点还算聪明,其实也是迫不得已的。
我的学习技巧
刚开始,我觉得主要的问题在于你晓得不晓得,而不是理解不理解,某个子系统的实现采用了某种策略、方法,而你在学习中须要做的就是晓得有那么一回事儿,之后才是理解所描述的策略或则技巧。
按照自己的学习经验,刚开始学习内核的时侯,我觉得要做的是在自己的脑海中构建起内核的大体框架,理解各个子系统的设计理念和建立思想,这种理念和思想会从宏观上呈送给你清晰的脉络,如同一个去不仅枝树叶叶的小树的主干,一目了然;其实,肯定都会涉及到具体的实现方式、函数,并且此时接触到的函数或则方式坐落内核实现的较高的层次,是主(要)函数,早已了解到这种函数,针对的是什么设计思想,实现了哪些样的功能,达成了哪些样的目的,混个脸熟的说法在这里也是创立的。至于该主函数所调用的其它的辅助性函数就等同于枝树叶叶了,何必太早就去探询。此时,也就初步构建起了内核子系统框架和代码实现之间的关联,关联虽然很简单,例如一听到某个函数名子,就想起这个函数是针对那个子系统的,实现了哪些功能。
我觉得此时要看的就是LKD3,这本书算是泛泛而谈,主要就是从概念,设计,大的实现方式上描述各个子系统,而对于具体的相关的函数实现的代码讲解甚少涉及(对比于ULK3,此书主要就是关于具体函数代码的具体实现的深入剖析,其实,你也可以看,而且过早看这本书,会觉得很苦闷,很无趣无味,基本上都是函数的实现),极少,但不是没有,这就挺好,满足我们当前的需求,还防止我们过早深入到实际的代码中去。并且本书在一些重要的点上还给出了写程序时的注意事项,算是指导性建议。主要的子系统包括:显存管理,进程管理和调度,系统调用,中断和异常,内核同步,时间和定时器管理,虚拟文件系统,块I/O层,设备和模块。(这儿的先后次序似乎就是LKD3的目录的次序)。
我学习的时侯是三本书交叉着看的,先看LKD3,专于一个子系统,主要就是了解设计的原理和思想,其实也会遇到对一些主要函数的介绍,但大多就是该函数基于上面介绍的思想和原理完成了哪些样的功能,该书并没有就函数本身的实现进行深入分析。之后再看ULK3和PLKA上看同样的子系统,而且并不仔细剖析底层具体函数的代码,只是简略地、不求甚解地看,甚至不看。由于,有些时侯,在其中一本书的某个点上,卡壳了,不是很理解了,在另外的书上你可能就遇到对同一个问题的不同角度的描述,说不准哪句话能够让你恍然活泼,如醍醐灌顶。我常常见到此类情况。
并不是说学习过程中对一些函数体的实现完全就忽视掉,只要自己想彻底了解其代码实现,没有谁会制止你。我是在反复阅读过程中渐渐深入的。例如VFS中文件打开须要对路径进行剖析,须要考虑的细节不少(.././之类的),而且其代码实现是挺好理解的。再例如,CFS调度中按照shedulelatency、队列中进程个数及其nice值(使用的是动态优先级)估算出分配给进程的时间片,没理由不看的,这个太重要了,但是也很有意思。
ULK3也会有设计原理与思想之类的概括性介绍,基本上都坐落某个主题的开篇段落。并且更多的是对支持该原理和思想的主要函数实现的具体剖析,同样在首段,一句话综述函数的功能,之后对函数的实现以1、2、3,或则a、b、c步骤的方式进行讲解。我只是有选择性的看,有时侯对照着用sourceinsight打开的源码,确认一下代码大体上确实是按书中所描述的步骤实现的,就当是降低感性认识。因为步骤中参杂着各类针对不同实现目的安全性、有效性检测,倘若不理解就先跳过。这并不阻碍你对函数体功能实现的整体掌握。
PLKA介于LKD3和ULK3之间。我认为PLKA的作者(看相片,真一日本帅男子,技术这么了得)肯定看过ULK,无论他的初衷还是有意,其实PLKA还是跟ULK有所不同,对函数的仔细讲解都做补充说明,除去函数体中边边角角的情况,例如一些特殊情况的处理,有效性检测等,而不阻碍对整个函数体功能的理解,这种他都有所交待,做了申明;并且,如同LKD3一样,在个别点上也给出了指导性编程建议。作者们甚至对同一个主要函数的讲解的着重点都不一样。这样的话,对我们学习的人而言,有助于加深理解。另外,我觉得很重要的一点就是PLKA针对的2.6.24的内核版本,而ULK是2.6.11,LKD3是2.6.34。在个别方面PLKA比较接近现代的实现。虽然作者们之所以分别选择11或则24,都是由于在版本发行树中,这两个版本在个别方面都做了不小的变动,或则说是具有标志性的转折点(这种信息大多是在书中的序言部份介绍的,具体的细节我想不上去了)。
IntelV3,针对X86的CPU,本书自然是系统编程的权威。内核部份实现都可以在本书找到其症结。所以,在读以上三本书某个子系统的时侯,不要忘掉可以在V3中相应章节找到一些基础性支撑信息。
在读书过程中,会形成相当多的疑惑,这一点是确信无疑的。大到搞不明白一个设计思想,小到不理解某行代码的用途。各个方面,各类疑惑,你完全可以把不理解的地方都记录出来(不过,我并没有那么做,没有把疑惑全部记出来,只标记了极少一部份我觉得很关键的几个问题),专门讲到一张纸上,不对,一个本上,我确信会形成如此多的疑惑,不然内核相关的峰会早就可以关掉了。虽然,大部份的问题(其中好多问题都是你晓得不晓得有如此一回事的问题)都可以迎刃而解,只要你肯回头再看,书读百遍,其义自现。多看几遍,前前后后的联系明白个七七八八是没有问题的。我也如此做了,针对个别子系统也看了好几遍,切身感受。
当你按次序学习这种子系统的时侯,上面的章节很可能会引用前面的章节,如同PLKA的作者说的那样,完全没有向后引用是不可能的,他能做的只是尽量降低这些引用而又不损害你对当前问题的理解。不理解,没关系,跳过就行了。前面的章节同样会有往前章节的引用,不过这个问题就简单一些了,你可以再回头去看相应的介绍,当时你不太理解的东西,很可能这个时侯就晓得了它的设计的目的以及具体的应用。不求甚解只是暂时的。例如说,内核各个子系统之间的交互和引用在代码中的彰显就是实现函数穿插调用,例如你在显存管理章节学习了的显存分配和释放的函数,而你是了解显存在先的,在学习驱动或则模块的时侯才会遇到这种函数的调用,这样也就比较容易接受,不至于太过沮丧;再例如,你了解了系统时间和定时器的管理,再回头看中断和异常中bottomhalf的调度实现,你对它的理解都会加深一层。
子系统进行管理工作须要大量的数据结构。子系统之间交互的一种方法就是各个子系统各自的主要数据结构通过表针成员互相引用。学习过程中,参考书上在讲解某个子系统的时侯会对数据结构中主要成员的用途解释一下,但肯定不会覆盖全部(成员比较多的情况,比如task_struct),对其它子系统基于某个功能实现的引用可能解释了,也可能没做解释,还可能说这个变量在何处会做进一步说明。所以,不要苦恼于一个不理解的点上,姑且放过,回头还可以看的。之间的联系可以在对各个子系统都有所了解以后再完善上去。显然,我一直在指出先理解概念和框架的重要性。
等我们完成了构建框架这一步,就可以选择一个比较感兴趣的子系统,例如驱动、网络,或则文件系统之类的。这个时侯你再去深入了解底层代码实现,相较于一开始就钻研代码,更容易一些,但是遇到了不解之处,或则忘掉了某个方面的实现,此时你完全可以找到相应的子系统,由于你晓得在哪去找,查漏补缺,除了完成了对当前函数的钻研,并且可以回顾、温习原先的内容,融会贯通的时机就在这儿了。
《深入理解linux虚拟显存》(2.4内核版本),LDD3,《深入理解linux网路技术黑幕》,几乎每一个子系统都须要一本书的容量去讲解,所以说,刚开始学习不宜对某个模块太过深入,等对各个子系统都有所了解了,再有针对性的去学习一个特定的子系统。这时侯对其它系统的引述都可以让我们不再倍感沮丧、复杂,不知所云。
例如,LDD3中的以下所列章节:构造和运行模块,并发和竞态,时间、延迟及减缓操作,分配显存,中断处理等,都属于驱动开发的支撑脾气系统,虽然本书对这种子系统都专门开辟一个章节进行讲解,而且详尽程度如何能比得上PLKA,ULK3,LKD3这三本书,看完这三本书,你会发觉读LDD3那些章节的时侯简直跟喝白滚水一样,太随便了,由于LDD3的讲解比之LKD3更简略。打好了基础,PCI、USB、TTY驱动,块设备驱动,网卡驱动,须要了解和学习的东西就比较有针对性了。这种子系统就属于通用子系统,了解过后,基于这种子系统的子系统的开发—驱动(需进一步针对硬件特点)和网路(需进一步理解各类合同)—相对而言,其学习难度大大增加,学习进度大大推进,学习效率大大提高。说着容易做来难。达到这样一种疗效的前提就是:必须得静下心来,认真读书,要看得进去,PLKA,ULK3厚得都跟板砖块儿一样,令人望之生畏,假如没有兴趣,没有热情,没有毅力,无论怎样都是不行,由于须要时间,须要很长时间。我并不是说必须打好了基础才可以进行驱动开发,只是说打好了基础的情况下进行开发会更轻松,更有效率,并且自己对内核代码的驾驭能力会更强悍。这只是我个人看法,我自己的学习方法,仅供参考。
语言
PLKA是个爱尔兰人用英语写的,后来翻译成中文,又从英语翻译成英文,我在网上书城里没有找到它的纸质中文版,所以就买了英文版的。ULK3和LKD3都是英语版的。大牛们写的书,措词造句真的是简约,易懂,看原版对我们学习计算机编程的程序员来说完全不成问题,最好原汁原味。假如一本书确实翻译地挺好,我们其实可以看英文版的,用母语进行学习,理解速率和学习进度其实是很快的,不作他想。看中文的时侯不要头脑里想着把他翻译成英文,没必要。
API看法
“比起晓得你所用技术的重要性,成为某一个非常领域的专家是不重要的。晓得某一个具体API调用一点用处都没有,当你须要他的时侯只要查询下就好了。”这句话始于我听到的一篇翻译过来的博客。我想指出的就是,这句话针应用型编程再合适不过,而且内核API就不完全这么。
内核相当复杂,学习上去很不容易,而且当你学习到一定程度,你会发觉,假如自己准备写内核代码,到最后要关注的依然是API插口,只不过这种API绝大部份是跨平台的,满足可移植性。内核黑客基本上早已标准化、文档化了这种插口,你所要做的只是调用而已。其实,在使用的时侯,最好对可移植性这一话题在内核中的编码约定烂熟于心,这样才能写出可移植性的代码。如同应用程序一样,可以使用开发商提供的动态库API,或则使用开源API。同样是调用API,不同点在于使用内核API要比使用应用API了解的东西要多出许多。
当你了解了操作系统的实现—这些实现可都是对应用程序的基础性支撑啊—你再去写应用程序的时侯,应用程序中用到的多线程,定时器,同步锁机制等等等等,使用共享库API的时侯,联系到操作系统,因而把对该API的文档描述同自己所了解到的那些方面在内核中的相应支撑性实现结合上去进行考虑,这会指导你选择使用哪一个API插口,选出效率最高的实现形式。对系统编程颇具了解的话,对应用编程不无裨益,甚至可以说是大有益处。
设计实现的本质,晓得还是理解
操作系统是介于底层硬件和应用软件之间的插口,其各个子系统的实现很大程度上依赖于硬件特点。书上介绍这种子系统的设计和实现的时侯,我们读过了,也就晓得了,若果再深入考虑一下,为何整体构架要根据这些形式组织,为何局部函数要遵守这样的步骤处理,知其然,知其所以然,假如你晓得了某个功能的实现是由于芯片就是如此设计的,CPU就是如此做的,这么你的疑惑也就基本上到此为止了。再考量,就是芯片构架方面的设计与实现,对于程序员来讲,无论是系统还是应用程序员,足迹探究到这儿,早已解决了好多疑惑,由于我们的工作性质偏软,而这种东西实在是够硬。
例如,ULK3中讲解的中断和异常的实现,究其症结,那是由于Intelx86系列就是如此设计的,去瞧瞧IntelV3指南中相应章节介绍,都可以为ULK3中描述的代码实现方法找到注解。还有时间和定时器管理,同样可以在IntelV3对APIC的介绍中获取足够的信息,操作系统就是根据这种硬件特点来实现软件方法定义的。
又是那句话,不是理解不理解的问题,而是晓得不晓得的问题。有时侯,晓得了,就理解了。在整个学习过程中,晓得,理解,晓得,理解,晓得……,交叉反复。为何开始和结尾都是晓得,而理解只是中间步骤呢?世界上万事万物自有其规律,人类只是发觉而已,实践是第一位的,实践就是晓得的过程,实践形成经验,经验的总结就是理论,理论始于实践,理论才须要理解。我们学习内核,深入研究,搞来搞去,又回到了芯片上,芯片是物质的,芯片的功用基于自然界中物质本有的化学和电子特点。追本探源,此之谓也。
动手写代码
纸上得来终觉浅,绝知此事要笃行。只看书是绝对不行的,一定要结合课本给出的编程建议自己敲代码。刚开始就以模块方式测试好了,或则自己编译一个开发版本的内核。一台机器的话,使用UML形式调试,内核控制路走到哪一步,单步调试瞧瞧程序执行过程,比书上的讲解更直观明了。一定要动手实际操作。
参考书
LDD3LinuxDeviceDriver3rd
LKD3LinuxKernelDevelopment3rd
ULK3UnderstandingtheLinuxKernel3rd
PLKAProfessionalLinuxKernelArchitecture
UMLUserModeLinux
IntelV3Intel?64andIA-32ArchitecturesSoftwareDeveloper’sManualVolume3(3A,3B&3C):SystemProgrammingGuide
作者在写书的时侯RED HAT LINUX 9.0,都是以自己的理解组织内容,从自己的观点看待一个主题,关注点跟作者自身有很大的关系。出书的时间有先后,后来人针对同一个主题想要出书而又不落入窠臼,最好有自己的切入形式linux内核驱动api手册,从自己的角度讲解相关问题,这才值得出这本书,千篇一律是个掉价的行为,书就不值钱了。
尽信书不如无书。
此处是一篇关于LKD3的书评,强调了其中的错误,当你读完的时侯,不妨去找找,看一下自己在其中所描述的地方有哪些非常的印象。
此处是一篇对ULK3的介绍,我觉得其中很关键的几句话就可以给本书定位:
Manyofthekeycontrolpathsinthekernelaredescribed,stepbystep;
一步一步地述说内核控制路径的实现。
Thelevelofdetailsometimesmakesithardtogetasenseforthebigpicture,butitdoeshelpsomebodytryingtofigureouthowaparticularfunctionworks.
对代码讲解的详尽程度有时侯很难让读者把松开它的主旨大意,而且确实有助于读者理解一个特定的函数究竟是怎样工作的。
Indeed,thatisperhapsthekeyfeaturewhichdifferentiatesthisbook.Itisverymucha“howitworks”book,designedtohelppeopleunderstandthecode.
事实上,这也正是本书与众不同的地方。更像一个“如何工作”的书,帮助读者理解代码实现。
Itpresentskernelfunctionsanddatastructures,stepsthereaderthroughthem,butdoesnot,forexample,emphasizetherulesforusingthem.UTLKisastudyguide,notaprogrammingmanual.
本书描述了内核函数和数据结构,引导读者游走于其间,然而,并没有注重指出使用它们的法则。UTLK是一本学习手册,而不是编程指南。
这几句话对本书的描述十分到位。基于此,作为指导性原则,我们就可以很有效率地使用它了。
看一本技术书籍,书中的引言部份绝对是首先应当翻阅的,其次就是目录。我发觉在阅读过程中我会频繁的查看目录,甚至是喜欢看目录。
结尾
兴趣的力量是无穷的。兴趣能带来激情,假如工作可以和兴趣结合到一起,工作上去就会有热情,这么工作就不只是工作了,更是一种享受。
Linux,我的兴趣,我的动力,我的方向,我的未来!
/uid-24669930-id-4039377.html
END