免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 882 | 回复: 0
打印 上一主题 下一主题

Linux内核源码目录介绍 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-02-29 14:46 |只看该作者 |倒序浏览
 Linux的内核源代码可以从很多途径得到,我一般常常去kernel.org看看。一般来讲,在安装的linux系统下,usr/src/linux目录下的东西就是内核源代码。源码的版本号有一个非常简单的编号约定:任何偶数的核心(例如2.0.30)都是一个稳定地发行的核心,而任何奇数的核心(例如2.1.42)都是一个开发中的核心。另外还可以从互连网上下载,解压缩后文件一般也都位于linux目录下。内核源代码有很多版本,目前最新的稳定版是2.2.14。  
  核心源程序的文件按树形结构进行组织,在源程序树的最上层你会看到这样一些目录:  
  · 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/i386/mm/Fault.c  
  · Kernel:主要的核心代码,此目录下的文件实现了大多数linux系统的内核函数,其中最重要的文件当属sched.c;同样,和体系结构相关的代码在arch/*/kernel中;  
  · Drivers: 放置系统所有的设备驱动程序;每种驱动程序又各占用一个子目录:如,/block 下为块设备驱动程序,比如ide(ide.c)。如果你希望查看所有可能包含文件系统的设备是如何初始化的,你可以看drivers/block/genhd.c中的device_setup()。它不仅初始化硬盘,也初始化网络,因为安装nfs文件系统的时候需要网络  
  · 其他: 如, Lib放置核心的库代码; Net,核心与网络相关的代码; Ipc,这个目录包含核心的进程间通讯的代码;Fs ,所有的文件系统代码和各种类型的文件操作代码,它的每一个子目录支持一个文件系统,例如fat和ext2;Scripts, 此目录包含用于配置核心的脚本文件等。一般,在每个目录下,都有一个 .depend 文件和一个 Makefile 文件,这两个文件都是编译时使用的辅助文件,仔细阅读这两个文件对弄清各个文件这间的联系和依托关系很有帮助;而且,在有的目录下还有Readme 文件,它是对该目录下的文件的一些说明,同样有利于我们对内核源码的理解。
(今天再补充一点有用的介绍)
相关内核源代码分析:  
1.系统的引导和初始化:Linux 系统的引导有好几种方式:常见的有 Lilo, Loadin引导和Linux的自举引导  
(bootsect-loader),而后者所对应源程序为arch/i386/boot/bootsect.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还要做一些其他的初始化工作;  
2.系统初始化后运行的第一个内核程序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就是中断服务程序之一;void __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中;  
3.中断总控程序主要负责保存处理机执行系统调用前的状态,检验当前调用是否合法, 并根据系统调用向量,使处理机  
跳转到保存在 sys_call_table 表中的相应系统服务例程的入口; 从系统服务例程返回后恢复处理机状态退回用户程序;  
而系统调用向量则定义在/usr/src/linux/include/asm-386/unistd.h 中;sys_call_table 表定义在  
/usr/src/linux/arch/i386/kernel/entry.S 中; 同时在 /usr/src/linux/include/asm-386/unistd.h  
中也定义了系统调用的用户编程接口;  
4.由此可见 , linux 的系统调用也象 dos 系统的 int 21h 中断服务, 它把0x80 中断作为总的入口, 然后  
转到保存在 sys_call_table 表中的各种中断服务例程的入口地址 , 形成各种不同的中断服务;  
由以上源代码分析可知, 要增加一个系统调用就必须在 sys_call_table 表中增加一项 , 并在其中保存好自己  
的系统服务例程的入口地址,然后重新编译内核,当然,系统服务例程是必不可少的。  
由此可知在此版linux内核源程序中,与系统调用相关的源程序文件就包括以下这些:  
1.arch/i386/boot/bootsect.S  
2.arch/i386/Kernel/setup.S  
3.arch/i386/boot/compressed/head.S  
4.arch/i386/kernel/head.S  
5.init/main.c  
6.arch/i386/kernel/traps.c  
7.arch/i386/kernel/entry.S  
8.arch/i386/kernel/irq.h  
9.include/asm-386/unistd.h  
当然,这只是涉及到的几个主要文件。而事实上,增加系统调用真正要修改文件只有include/asm-386/unistd.h  
和arch/i386/kernel/entry.S两个;  
【三】 对内核源码的修改:  
1.在kernel/sys.c中增加系统服务例程如下:  
asmlinkage int sys_addtotal(int numdata)  
{  
int i=0,enddata=0;  
while(i

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/55527/showart_486876.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP