linux 内核学习(2)

来源:互联网 发布:软件逆向工程培训 编辑:程序博客网 时间:2024/05/18 00:11
 linux内核源码树大体结构

由于linux的原代码持续在变化,所以不可能给出太详细的内容,只能指出一个特殊的驱动大概会出现在什么地方。

Makefile
这是整个的源码树的最顶层的Makefile。它定义了很多的有用的变量和规则,如默认的gcc编译标志。

arch/
所有的特殊的体系结构的代码都在这个目录和include/asm-<arch>目录下。每个体系在这个目录下都有自己的目录。像基于PowerPC的计算机的代码可以在arch/ppc目录下找到。你将会在这些目录下找到低级的内存管理,中断处理,早期初始化,汇编程序等很多东西。

crypto/
用于内核自身加密的API。

drivers/
大体上,在这个目录的子目录下驱动外设的代码。其中包括了显卡驱动,网卡驱动,低级的SCSI驱动等相似的东西。一些将所有同一类的驱动整合的高层次的代码可能与低层次的驱动不在同一个目录下。

fs/
一般的文件系统的代码(也就是VFS,或者虚拟文件系统)和其他不同的文件系统的代码都可以在这个目录下找到。你的根文件系统可能是ext2的,用来阅读ext2格式的代码在fs/ext2下。不是所有的文件系统被编译和运行,并且更晦涩的文件系统常常是那些在寻找内核工程的不错的候选者。

include/
大部分的在一个.c文件的开头被包含的头文件都能在这个目录中找到。体系结构的include文件在asm-<arch>目录下。部分内核构建是建立了软从asm到asm-<arch>的软链接,所以#include<asm/file.h>将会得到适和与体系结构的文件,而编码到.c文件中。另外的一些目录包含了没有特殊的体系构架的头文件。如果一个结构,常量或者变量被几个.c文件使用,那么他可能在其中的一个头文件中。

init/
这个目录下包含了文件main.c,version.c,和用来创建早期的用户空间(userspace)的代码。version.c定义了linux的版本的字符串。main.c可以被认为是内核的黏合剂。早期的用户空间提供了当内核启动时可用但是不需要在内核内部运行的功能。

ipc/
"IPC"是进程间的通信的意思。这个目录包含了共享内存,信号量和其他形式的IPC的代码。

kernel/
一般的内核级别不适合其他地方的代码都在这里。较高层次的系统调用在这儿,printk,调度,信号处理代码等等。

lib/
对所有内核代码同样有用的常规性代码被放在这里。一般的字符串操作,debugging例程和命令行语法分析的代码都在这儿。

mm/
在这个目录中是高级的内存管理的代码。虚拟内存(VM)是通过这些例程联合在arch/<arch>/mm/中的特定的对应体系结构的低层的体系结构的例程来实现。前期的引导内存管理,文件内存映射,页缓存管理,内存分配,RAM中页面的替换等等也是在这里实现的

net/
高层次的联网的代码被放在这里。低层的网络驱动将接收到的包向上传递并且把这一层发出的包打包。这一层次可能将数据传递到用户层次的运用,或丢弃数据,或在内核内部使用,这些取决于相应的包。

scripts/
这个目录包含了用来构建内核的有用的脚本,其中不包含任何结合进入内核的代码。比如各种配置工具把他们的脚本放在这里。

security/
这里放了linux中的不同的加密模块,像NSA提高linux的安全和套接字和网络安全检查hooks

sound/
声卡的驱动和其他的一些与声音相关的代码被放在这儿。

usr/
这个目录包含了构建包含了一个可用做早期的用户空间的根文件系统镜像cpio格式的归档的代码。

整个的linux内核的中心结合点是文件init/main.c。每个体系执行了一些底层次的设置函数之后执行在init/main.c中的start_kernel函数。


代码的执行顺序如下图

    特定体系的设置代码(在arch/<arch>/*)
   |
   v
   函数start_kernel()(在init/main.c)
   |
   v
   函数init()(在/init/main.c)
   |
   v
   用户层次的"init"程序。
   

In more detail, this is what happens:

    特定体系结构的设置的代码实现了:
          如果必要,打开并移动内核代码。
          初始化硬件
                可能包含设置低层次的内存管理。
          将控制权转交到函数start_kernel()

    start_kernel()所作的:
          打印内核的版本和命令行
          开始输出到开始输出到控制台
          允许中断
          校准延时循环。
          调用rest_init(),rest_init()功能:
                开始一个内核线程来运行init()函数。
               进入空循环
    init():
          启动另一个处理器(在一台SMP机器上)
          启动设配子系统
          挂载根文件系统
          释放未使用的内核内存
          运行/sbin/init(或 /etc/init)

运行到这里,用户级的init程序已经在运行了,他会作一些类似启动网络服务和在控制台运行getty。

注:有些地方是翻译的,意思可能表达的有点问题,还望多多指教。
原创粉丝点击