论坛 
IT客
设为首页
加入收藏
关于我们
首页  | 程序 | IT新闻 | IT基础 | 网络 | 系统 | 数据库 | 软件开发 | 软件下载 | 电影频道 | FLASH | 图片 | 技术文档 | 分类信息
网络 Cisco 网络设备 解决方案 系统 Windows Linux 服务器 系统安全 程序 Java Dotnet 数据库 Oracle MySQL MSSQL 软件开发 Web开发 桌面开发 IT基础 网页设计 平面设计 多媒体 工具软件 即时通讯 Flash FLASH爆笑 FLASH游戏 FLASH MTV FLASH彩铃 图片 明星 美女 笑话大全
子栏目  | Linux安装 | 常用命令 | 软件使用
首页 > 系统 > Linux > 新手入门 > Linux安装 >
 
Linux 内核解读入门篇
作者: 发布时间:2008-04-14 01:51:47 来源:

  针对好多Linux 爱好者对内核很有兴趣却无从下手,本文旨在介绍一种解读Linux内核源
  
  码的入门方法,而不是解说Linux复杂的内核机制。
  
  1.核心源程序的文件组织
  
  (1)Linux核心源程序通常都安装在/usr/src/Linux下,而且它有一个非常简单的编号
  
  约定:任何偶数的核心(例如2.0.30)都是一个稳定的发行的核心,而任何奇数的核心
  
  (例如2.1.42)都是一个开发中的核心。
  
  本文基于稳定的2.2.5源代码,第二部分的实现平台为 Redhat Linux 6.0。
  
  (2)核心源程序的文件按树形结构进行组织,在源程序树的最上层你会看到这样一些目
  
  录:
  
  ● Arch :arch子目录包括了所有和体系结构相关的核心代码。它的每一个子目录都代
  
  表一种支持的体系结构,例如i386就是关于intel cpu及与之相兼容体系结构的子目录。
  
  PC机一般都基于此目录;
  
  ● Include: include子目录包括编译核心所需要的大部分头文件。与平台无关的头文件
  
  在 include/linux子目录下,与 intel cpu相关的头文件在include/asm-i386子目录下
  
  ,而include/scsi目录则是有关scsi设备的头文件目录;
  
  ● Init: 这个目录包含核心的初始化代码(注:不是系统的引导代码),包含两个文件
  
  main.c和Version.c,这是研究核心如何工作的一个非常好的起点;
  
  ● Mm :这个目录包括所有独立于 cpu 体系结构的内存管理代码,如页式存储管理内存
  
  的分配和释放等,而和体系结构相关的内存管理代码则位于arch/*/mm/,例如arch/i38
  
  6/mm/Fault.c;
  
  ● Kernel:主要的核心代码,此目录下的文件实现了大多数Linux系统的内核函数,其
  
  中最重要的文件当属sched.c,同样,和体系结构相关的代码在arch/*/kernel中;
  
  ● Drivers:放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录,如/bl
  
  ock下为块设备驱动程序,比如ide(ide.c)。如果你希望查看所有可能包含文件系统的
  
  设备是如何初始化的,你可以看drivers/block/genhd.c中的device_setup()。它不仅初
  
  始化硬盘,也初始化网络,因为安装nfs文件系统的时候需要网络。
  
  其他如Lib放置核心的库代码; Net,核心与网络相关的代码;Ipc,这个目录包含核心的
  
  进程间通信的代码;Fs ,所有的文件系统代码和各种类型的文件操作代码,它的每一个
  
  子目录支持一个文件系统,例如fat和ext2; Scripts, 此目录包含用于配置核心的脚本
  
  文件等。
  
  一般在每个目录下都有一个 .depend 文件和一个 Makefile 文件,这两个文件都是编译
  
  时使用的辅助文件,仔细阅读这两个文件对弄清各个文件之间的联系和依托关系很有帮
  
  助,而且在有的目录下还有Readme 文件,它是对该目录下的文件的一些说明,同样有利
  
  于我们对内核源码的理解。
  
  2.解读实战:为你的内核增加一个系统调用
  
  虽然Linux 的内核源码用树形结构组织得非常合理、科学,把功能相关联的文件都放在
  
  同一个子目录下,这样使得程序更具可读性。然而,Linux 的内核源码实在是太大而且
  
  非常复杂,即便采用了很合理的文件组织方法,在不同目录下的文件之间还是有很多的
  
  关联,分析核心的一部分代码通常要查看其他的几个相关的文件,而且可能这些文件还
  
  不在同一个子目录下。
  
  体系的庞大复杂和文件之间关联的错综复杂,可能就是很多人对其望而生畏的主要原因
  
  。当然,这种令人生畏的劳动所带来的回报也是非常令人着迷的:你不仅可以从中学到
  
  很多的计算机的底层的知识(如下面将讲到的系统的引导),体会到整个操作系统体系
  
  结构的精妙和在解决某个具体细节问题时算法的巧妙,而且更重要的是在源码的分析过
  
  程中,你就会被一点一点地、潜移默化地专业化;甚至,只要分析1/10的代码后,你就
  
  会深刻地体会到,什么样的代码才是一个专业的程序员写的,什么样的代码是一个业余
  
  爱好者写的。
  
  为了使读者能更好的体会到这一特点,下面举了一个具体的内核分析实例,希望能通过
  
  这个实例,使读者对 Linux 的内核组织有些具体的认识,读者从中也可以学到一些对内
  
  核的分析方法。
  
  以下即为分析实例:
  
  (1)操作平台
  
  硬件:cpu intel Pentium II ;
  
  软件:Redhat Linux 6.0; 内核版本2.2.5
  
  (2)相关内核源代码分析
  
  ① 系统的引导和初始化:Linux 系统的引导有好几种方式,常见的有 Lilo、Loadin引
  
  导和Linux的自举引导(bootsect-loader),而后者所对应源程序为arch/i386/boot/bo
  
  otsect.S,它为实模式的汇编程序,限于篇幅在此不做分析。无论是哪种引导方式,最
  
  后都要跳转到 arch/i386/Kernel/setup.S。 setup.S主要是进行时模式下的初始化,为
  
  系统进入保护模式做准备。此后,系统执行 arch/i386/kernel/head.S (对经压缩后存
  
  放的内核要先执行 arch/i386/boot/compressed/head.S); head.S 中定义的一段汇编
  
  程序setup_idt ,它负责建立一张256项的 idt 表(Interrupt Descriptor Table),此表
  
  保存着所有自陷和中断的入口地址,其中包括系统调用总控程序 system_call 的入口地
  
  址。当然,除此之外,head.S还要做一些其他的初始化工作。
  
  ② 系统初始化后运行的第一个内核程序asmlinkage void __init start_kernel(void)
  
   定义在/usr/src/linux/init/main.c中,它通过调用usr/src/linux/arch/i386/kernel
  
  /traps.c 中的一个函数 void __init trap_init(void) 把各自陷和中断服务程序的入
  
  口地址设置到 idt 表中,其中系统调用总控程序 system_cal就是中断服务程序之一;vo
  
  id __init trap_init(void)函数则通过调用一个宏 set_system_gate(SYSCALL_VECTOR
  
  ,&system_call), 把系统调用总控程序的入口挂在中断0x80上。
  
  其中SYSCALL_VECTOR是定义在 /usr/src/linux/arch/i386/kernel/irq.h中的一个常量
  
  0x80, 而 system_call 即为中断总控程序的入口地址,中断总控程序用汇编语言定义
  
  在/usr/src/linux/arch/i386/kernel/entry.S中。
  
  ③ 中断总控程序主要负责保存处理机执行系统调用前的状态,检验当前调用是否合法,并
  
  根据系统调用向量,使处理机跳转到保存在 sys_call_table 表中的相应系统服务例程
  
  的入口, 从系统服务例程返回后恢复处理机状态退回用户程序。
  
  而系统调用向量则定义在/usr/src/linux/include/asm-386/unistd.h 中,sys_call_t
  
  able 表定义在 /usr/src/linux/arch/i386/kernel/entry.S 中, 同时在 /usr/src/l
  
  inux/include/asm-386/unistd.h 中也定义了系统调用的用户编程接口。
  
  ④ 由此可见 ,Linux 的系统调用也像 dos 系统的 int 21h 中断服务, 它把0x80 中断
  
  作为总的入口, 然后转到保存在 sys_call_table 表中的各种中断服务例程的入口地址
  
   , 形成各种不同的中断服务。
  
  由以上源代码分析可知,要增加一个系统调用就必须在 sys_call_table 表中增加一项
  
  ,并在其中保存好自己的系统服务例程的入口地址,然后重新编译内核,当然,系统服务
  
  例程是必不可少的。
  
  由此可知,在此版Linux内核源程序<2.2.5>中,与系统调用相关的源程序文件就包括以下
  
  这些:
  
  * arch/i386/boot/bootsect.S
  
  * arch/i386/Kernel/setup.S
  
  * arch/i386/boot/compressed/head.S
  
  * arch/i386/kernel/head.S
  
  * nit/main.c
  
  * rch/i386/kernel/traps.c
  
  * rch/i386/kernel/entry.S
  
  * rch/i386/kernel/irq.h
  
  * nclude/asm-386/unistd.h
  
  当然,这只是涉及到的几个主要文件。而事实上,增加系统调用真正要修改的文件只有
  
  include/asm-386/unistd.h 和arch/i386/kernel/entry.S两个。
  
  (3)源码的修改
  
  ① kernel/sys.c中增加系统服务例程如下:
  
  asmlinkage int sys_addtotal(int numdata)
  
  {
  
  int i=0,enddata=0;
  
  while(i<=numdata)
  
  enddata+=i++;
  
  return enddata;
  
  }
  
  该函数有一个 int 型入口参数 numdata , 并返回从 0 到 numdata 的累加值,然而也
  
  可以把系统服务例程放在一个自己定义的文件或其他文件中,只是要在相应文件中作必
  
  要的说明。
  
  ②把smlinkage int sys_addtotal( int) 的入口地址加到sys_call_table表中。
  
  
  
评论】【加入收藏夹】【 】【打印】【关闭
※ 相关信息
 ·轻松在Redhat linux 7.3安装新字  (2008-04-14)
 ·Linux操作系统网卡安装指南  (2008-04-14)
 ·linux下安装配置socks5代理  (2008-04-14)
 ·在 Linux 上安装 PostgreSQL  (2008-04-14)
 ·如何远程安装Linux  (2008-04-14)
 ·Linux上Sybase ASE11.9.2的安装、  (2008-04-14)
 ·在Linux2.0上安装AS11.9.2  (2008-04-14)
 ·红旗linux(Server2.0)下安装Orac  (2008-04-14)
 ·安装Linux无盘工作站(上)  (2008-04-14)
 ·安装Linux无盘工作站(下)  (2008-04-14)

发表评论
用户名: 密码:
验证码: 匿名发表
 
 搜索文章
 最新文章
·Win2K入侵检测实例分析
·Win2000 Server安全入门
·使用微软安全工具包加固Win2
·Windows2000安全检查清单
· 安全管理
·利用安全工具包保持系统的最
·怎么实施和做好入侵检测
·Win2k建立安全WEB站点的解决
·用“$”来加强共享资源的安全
·让你的IIS无懈可击
 热点文章 
· 我的xfce学习笔记(汉化)
·三个方法优化MySQL数据库查询
·IPW2100安装详细步骤说明
·Gnuplot科学绘图——入门篇
·Linux下使用Evolution收发Em
·在Archlinux 安装Maya7.01
·安装Linux中文输入法fcitx
·向Linux迁移的人才准备
·使用指南:好用的播放器mpd
·你应该知道的10个MySQL客户启

社区关于我们广告业务信息反馈合作伙伴网站地图
ITKee.Com 版权所有
Copyright © 2008 All rights reserved