如何开始研究内核技术

时间:2021-10-16 13:00:07

==www.cciss.cn.==
                           ==bbs.cciss.cn.==
                             
                    如何开始研究内核技术--如何入手?

|=---------------=[ 如何开始研究内核技术 ]=------------------------=|
|=-----------------------------------------------------------------=|
|=---------------=[ 7all<7all7_at_163.com> ]=----------------------=|
|=-----------------------------------------------------------------=|
|=---------------=[ 版权所有:bbs.cciss.cn / bbs.idf.cn]=-----------=|


备注:本文的一些观点和方法仅代表个人观点,如果大家有什么好的建议,可以发mail
给我,不胜感激:)(bloodfall@msn.com)
本来这篇文章没有打算放出来,技术太过于简单了,最后考虑了下,觉得可能会对初学者有
帮助吧,就放了出来.
--] 开篇的笑话
开始接触*BSD的时候,我也是找不到方向的,为了测试一个问题,我曾经把FreeBSD的内核ELF
文件下载下来进行反编译,大家先别笑.虽然我知道*BSD是开源的,但是我当时真的没有找到
那个部分的源代码,再加上我自己老感觉自己汇编功底好,嘿嘿,于是有那么几天时间我都在
边测试边看汇编代码来解决问题,现在想起来的确是个很黑色的幽默.看汇编代码是没有办
法与看可爱的C源码相提并论的,这种感觉就好像你在喝醉的时候,突然喝到老婆为你准备的
茶水.我不知道这篇文章是否对大家有用,但是如果你感觉有用的话,不妨在偶尔碰见我的时
候请我喝杯咖啡,就当是看了这篇文章对你有帮助的报酬吧:)本来是想喝啤酒的,可惜已经
戒酒了:).

--] 概述
  随着Linux内核研究系列图书的出现,内核研究技术也成了一些技术爱好者的一个选择。
研究内核可以更好的了解OS运行的机理,并能够提高自己对于驱动、内存管理等底层技术
的掌握,而且因为内核源码的编程质量都很高,顺便还可以提高程序设计能力。
  如果是研究Linux的内核,那么现行的Linux内核研究系列图书很多,如:
《Linux内核源代码情景分析(上下册)》、《Linux内核分析及编程》等。这些图书都从基
础开始一层一层的谈论到了Linux内核的一些知识体系,有些资料还针对硬件体系架构进行
了前面章节的描述,对于提高底层编程知识有很大的帮助。
  这里我想阐述的意思是,如果去研究FreeBSD内核、OpenBSD内核的话,如何下手才可以
更快的熟悉内核。随着Linux的越来越庞大,Linux的目标逐渐的转变到用户应用方面,例
如Linux越来越追求用户界面的人性化设计等。而对于FreeBSD、OpenBSD等*BSD操作系统,
却始终坚持走Server的路线,当然*BSD做为个人操作系统也是很安全的,但是*BSD做为
Server的使用比例要比个人PC的使用比例高了很多很多。
  这里我们从FreeBSD入手来分析如何下手才能更好的开始我们的内核分析之旅:)
  A: 系统结构
  B: FreeBSD启动过程
  C: SYSCALL系统调用
  D: KERNEL模块
  E: ISA/PCI模块
  F: TCP/IP的*BSD实现
  G: 总结
 
  由于本文仅想通过一些想法来帮助大家认识到从何处下手分析*BSD,所以很多地方都是些理论性质
的说明,而且本文仅为个人观点有不当之处还请大家指正.
 
--] 系统结构
  熟悉FreeBSD的系统结构是开始分析内核的关键部分,只有熟悉了系统的大体组成部分才可以更好的
的完成对内核部分的分析.如果连基本的系统结构都没有搞清楚,别说研究内核,就算是搞*BSD下面的开
发都是很累人的事情,所以要想研究其内核部分,就先把*BSD当成自己的女朋友那样的来照顾呵护,只要
前期把*BSD"呵护"好了,那么针对*BSD的内核研究也就是很easy的事情了:)
Nothing,So Easy.个人感觉,其实类Unix系统的开发是很好玩的事情,因为可以在开发的过程中了解
更多的OS本身的底层知识,而且可以更好的熟悉很多硬件知识.通读完*BSD的代码,或许就会知道原来C
语言还可以这么写.
对于一个OS的组成而言,其基本组成结构如下所示:
  --系统启动过程(如何通过BIOS引导系统启动并加载运行内核).
  --内核对象,内核是如何work的.
  --文件系统,OS是如何实现文件系统的.
  --设备驱动程序,OS如何管理与控制设备.
  抛弃其他的一些杂乱的"零部件",那么一个OS的组成部分可以简单的理解为以上的几个部分,实现了OS启动
即可以把OS内核部分加载到内存并启动OS,实现了文件系统则可以完成对硬盘的相关操作,实现了设备驱动
程序则完成了OS与计算机周边其他设备的通讯与使用.所以我觉得一个OS的基本结构正是这几个关键的部分
组成的,至于网络协议的实现,其他功能的扩充只是在内核层/应用层对OS又进行了包装和再设计而已.
  而以上所涉及的四个方面的知识就需要大家熟悉计算机的硬件设备的特性,然后针对硬件设备的特性对OS
进行设计.我目前有个不成熟的想法,想针对*BSD的OS系统二次开发一个Server级别的精简版本的*BSD系统,
这个*BSD格式的OS以处理WEB服务为主,然后针对WEB Server开发相关的WEB FireWall,增强的IDS入侵检测,
病毒检测系统,防火墙检测系统.因为该OS可以精简一些冗余的功能,应该会在性能和冗余性方面获得比较好
的效果,当然这只是一个想法,具体的实施方案还没有整体的成型,在这里提及这个问题的原因也是想有了解
这些知识的朋友加以指点:)
  希望有兴趣研究*BSD内核的朋友,可以先考虑在熟悉完系统结构,基本的系统架构后再开始对*BSD系统的内核
分析.当然我这个办法可能不会适合任何人,只所以这样来写,是为了给一些找不到方向的朋友一些自己的观点.
 
--] FreeBSD启动过程
  熟悉OS的启动过程,是为了研究*BSD是如何启动和加载运行内核对象的.其实如果单纯从研究*BSD内核本身而
言,是可以把这个过程给暂时省掉的.不过省去了这个环节有些时候难免会感觉不够完美.特别是在分析Kernel的
时候,就会有些迷惑的地方.所以建议先从FreeBSD的启动过程源代码来分析OS的启动过程,从头开始摸索,直到摸
索到脚趾甲,这种感觉就是"完美":)
  FreeBSD的硬盘启动过程大体如下所示:
  --BIOS POST
  --boot0
  --boot2
  --loader
  --kernel初始化
  我先解释下为什么没有boot1阶段,因为boot1阶段是软盘启动的过程,而我们这里为硬盘直接启动,所以省去了
  boot1的启动阶段.
  1: BIOS POST
    POST其实只是一个概念而已,哈哈...开个玩笑.POST就是加电自检的过程,我想这个大家都是熟悉的,就是在
加电后对整个计算机设备的检查,最后到引导设备是光驱/硬盘/软盘,然后根据引导设备进行下面的操作,其实现
在的BIOS都可以选择引导设备的,我想这个我也不用多罗嗦.
    有个问题我顺便说明下,POST过程的最后是执行int 0x19指令,这个指令从引导设备第一个扇区读取512字节,
装入地址0x7c00.这里的512个字节正好是主引导分区的地方,到了主引导分区了...我想下面我可以省去了,这个
大家都知道主引导分区是干什么用的:)到了这里BIOS POST结束.
  2: boot0阶段
    可爱的boot0其实就是前面POST最后阶段加载的512个字节的主引导分区内容,正是这512个字节的内容实现了
*BSD启动的一个关键过程,512个字节的内容还包括硬盘分区等信息.不过这个boot0.s的代码的确是高人所写,看
了就会知道.即使是FreeBSD官方网站也把这段代码的作者称赞的五体投地,开始的时候我没有什么反应,没有办法
搞技术人的通病,但是看完后,我利马决定将五体投地改为五马分尸...因为这么强的人留在世上是个"*":))
  3: boot2阶段
    可爱的boot2阶段也是被boot0给勾引出来的,上面在讨论boot0的时候并没有说boot0干了什么,其实我是想
大家可以往下看而已.boot0的作用就是把程序的指向引导到可引导扇区的第一个扇区,而在这里正好住着boot2,
由于boot0长的比boot1帅很多,所以每次boot0一叫,boot2会利马出来...不过我始终纳闷,要是boot1叫boot2的时
候,boot2不出来的话那boot2就是一个很完美的女孩了.可惜,如果真的boot1叫boot2,boot2也不出来...那么你的
*BSD就出问题了,赶紧想办法进行系统灾难恢复吧.
  4: loader阶段
    loader阶段是为了加载内核,等待内核加载进入内存,loader就开始load...loader位于/boot/loader,loader
是可配置的,而且loader本身内置了很多的命令选项.这个阶段也算是启动过程的最后阶段了,因为内核已经加载
进入了内存内并被load...
  5: kernel初始化
    loader最后跳动内核入口,然后内核就会做下面的一些事情:
    初始化内核的可调整参数,这些参数由引导程序传来
        准备GDT(全局描述符表)       
        准备IDT(中断描述符表)
        初始化系统控制台       
        初始化DDB(内核的点调试器),如果它被编译进内核的话       
        初始化TSS(任务状态段)       
        准备LDT(局部描述符表)       
        建立proc0(0号进程,即内核的进程)的pcb(进程控制块)
       
        备注:这里没有分析全面.

--] SYSCALL系统调用
  写过shellcode的朋友都非常熟悉syscall,系统调用也是从用户模式到内核模式的一个接口,所以我自己感觉应该
先从系统调用开始学起.系统调用有很多很多...哈哈,吓唬吓唬大家,其实大概有300多个吧:)很幸运的是我刚把
syscall的系统函数看完,看的我是热血沸腾的...好东西的确是好东西,看完了syscall的代码就会对*BSD的熟悉又
进了一步:)
  如果大家对UNIX感兴趣不妨看看syscall的相关代码,我自己感觉在这里下手也是很不错的做法.

--] KERNEL模块
  kernel模块是可增加或删除的,kernel module的出现给写内核程序的程序员提供了便利,因为可以通过kernel module
的加载/卸载来免除重启机器调试内核型代码的麻烦:)
  关于kernel模块的问题,大家可以在<<Simple Analyzing BSD Difference Filiation Kernel>>该文档内找到相关的
简单源代码,在这个文档内我也对kernel module进行了简单的说明.

--] ISA/PCI模块
  Not Write:-)

--] TCP/IP的*BSD实现
    Not Write:-)

--] 总结
    由于时间关系,该文档并未完全完成,但是还是决定先发布下:)到目前为止,自己都不知道什么时候有时间能够安静的书写
完该文档,或许是春节,或许是2007年的某一天,但希望该文档对大家有帮助:-)

--] 参考
FreeBSD官方结构手册 http://cnsnap.cn.freebsd.org/doc/zh_CN. … -handbook/