当前位置:文档之家› Linux内核源代码漫游

Linux内核源代码漫游

Li nu x内核源代码漫游创建时间:2001-10-1121时13分

Linux内核源代码漫游

Alessandro Rubini 著, rubini@pop.systemy.it 赵

炯译,gohigh@https://www.doczj.com/doc/946251040.html, (https://www.doczj.com/doc/946251040.html,)

本章试图以顺序的方式来解释Li nu x源代码,以帮助读者对源代码的体系结构以及很多相关的unix特性的实现有一个很好的理解。目标是帮助对Lin ux不甚了解的有经验的C 程序员对整个L i nu x的设计有所了解。这也就是为什么内核漫游的入点选择为内核本身的启始点:系统引导(启动)。

这份材料需要对C语言以及对Un i x的概念和P C机的结构有很好的了解,然而本章中并没有出现任何的C代码,而是直接参考(指向)实际的代码的。有关内核设计的最佳篇幅是在本手册的其它章节中,而本章仍趋向于是一个非正式的概述。

本章中所参阅的任何文件的路径名都是指主源代码目录树,通常是/u s r/s r c/li nu x。

这里所给出的大多数信息都是取之于Lin u x发行版 1.0的源代码。虽然如此,

有时也会提供对后期版本的参考。这篇漫游中开头有图标的任何小节都是强调 1.0版本后对内核的新的改动。如果没有这样的小节存在,则表示直到版本 1.0.9-1.1.76,没有作过改动。

有时候本章中会有象这样的小节,这是指向正确的代码以对刚讨论过的主题取得

更多信息的指示符。当然,这里是指源代码。

引导(启动)系统

当P C的电源打开后,80x86结构的CP U将自动进入实模式,并从地址0xF FFF0开始自动执行程序代码,这个地址通常是ROM-B IOS中的地址。PC机的BIOS将执行某些系统的检测,在物理地址0处开始初始化中断向量。此后,它将可启动设备的第一个扇区读入内存地址0x7C00处,并跳转到这个地方。启动设备通常是软驱或是硬盘。这里的叙述是非常简单的,但这已经足够理解内核初始化的工作过程了。

Li nux的最最前面部分是用8086汇编语言编写的(bo ot/bo ot s e c t.S),它将由BIOS

读入到内存0x7C00处,当它被执行时就会把自己移到绝对地址0x90000处,并将启动设备

(bo ot/s et u p.S)的下2k B字节的代码读入内存0x90200处,而内核的其它部分则被读入到地址0x10000处。在系统加载期间将显示信息"L oa d in g..."。然后控制权将传递给bo ot/S et u p.S中的代码,这是另一个实模式汇编语言程序。

启动部分识别主机的某些特性以及vg a卡的类型。如果需要,它会要求用户为控制台选择显示模式。然后将整个系统从地址0x10000移至0x1000处,进入保护模式并跳转至系统的余下部分(在0x1000处)。

下一步是内核的解压缩。0x1000处的代码来自于z B oo t/head.S,它初始化寄存器并调用d e c om p r e ss_k e rn e l(),它们依次是由z B oo t/i n f l at e.c、z B oot/u n z i p.c和z B oo t/m isc.c组成。被解压的数据存放到了地址0x10000处(1兆),这也是为什么Li nu x不能运行于少于2兆内存的主要原因。[在1兆内存中解压内核的工作已经完成,见M em o r y S av e rs--ED]将内核封装在一个gz i p文件中的工作是由z B oo t目录中的M ak ef il e以及工具

完成的。它们是值得一看的有趣的文件。

内核发行版1.1.75将b oot和z B oo t目录下移到了a rc h/i386/boo t中了,这个改动意味着对不同的体系结构允许真正的内核建造,不过我将仍然只讲解有关i386的信息。解压过的代码是从地址0x10100处开始执行的[这里我可能忘记了具体的物理地址

了,

第 1 页共

9 页

因为我对相应的代码不是很熟],在那里,所有32比特的设置启动被完成:I DT、GDT以及L D T被加载,处理器和协处理器也已确认,分页工作也设置好了;最终调用

sta r t_ke rn e l子程序。上述操作的源代码是在bo ot/head.S中的,这可能是整个内核中最有诀窍的代码了。注意如果在前述任何一步中出了错,计算机就会死锁。在操作系统还没有完全运转

之前

是处理不了出错的。

sta r t_ke rn e l()是位于ini t/ma in.c中的,并且没有任何返回结果。从现在起的任何代码都是用C语言编制的,除了中断管理和系统调用的入/出代码(当然,还有大多数的宏都嵌入了汇编代码)。

让轮子转动起来

在处理了所有错综复杂的问题之后,sta r t_ke rn e l()初始化了内核的所有部分,尤其是:?设置内存边界和调用pa g in g_in i t();

?初始化中断、IR Q通道和调度;

?分析(解析)命令行;

?如果需要,就分配一个数据缓冲区(p r of il in g b u ff e r)以及其它一些小部分;

?校正延迟循环(计算“B ogo Mi p s”数);

?检查中断16是否能与协处理器工作。最后,为了生成初始进程,内核准备好了移至mo ve_t o_us e r_m od e(),它的代码也是在

同一个源代码文件中的。然后,所谓的空闲任务,进程号0就进入无限的空闲循环中运行。接着初始进程(in i t p r o c e ss)尝试着运行/et c/i ni t、/b i n/ini t或者/s b in/i ni t。

如果它们没有一个运行成功的,就会去执行代码“/b in/s h /etc/rc”并且在第一个终

端上生成一个根命令解释程序(r oot s he ll)。这段代码回溯至Li nu x0.01,当时操作系统只有一个内核,并且没有登录进程。

在从一个标准的地方(让我们假定我们有)用e x e c()执行了in i t初始化程序之后,内核就对程序的执行没有了直接的控制。从现在起它的规则是提供对系统调用的处理,以及为异步事件服务(比如硬件中断等)。多任务的环境已经建立,从现在起是i n i t程序通过fo r k()派生出的系统进程和登录进程来管理多用户的访问了。

由于内核是负责提供服务的,这个漫游文章将通过观察这些服务(“系统调用”)以及通过提供基本数据结构的原理和代码的组织结构继续讨论下去。

内核是如何看见一个进程的从内核的观点来看,一个进程只是进程表中的一个条目而已。而进程表以及各个内存管理表和缓冲存储器则是系统中最为重要的数据结构。进程表中

的各个单项是tas k_s t ruc t结构,是定义在inc lu de/l in ux/s c hed.h中的非常大的数据结构。在tas k_s t ruc t中保留着从低层到高层的信息,范围从某些硬件寄存器的拷贝到进程工作目录的in od e信息。

进程表既是一个数组和双链表,也是一个树结构。它的物理实现是一个静态的指针数组,它的长度是定义在i nc lu de/l in ux/tas k s.h中的常量N R_T A S K S,并且每个结构都位于一个保留内存页中。这个列表结构是通过指针n e x t_t a s k和p r e_t a s k构成的,而树结构则是非常复杂的并且我们在此将不加以讨论。你可能希望改动N R_T A S K S的默认值128,但你要保证所有源文件中相关的适当文件都要被重新编译过。

在启动引导过程结束后,内核将总是代表某个进程而工作,并且全局变量c u rr e n t---一个指向某个tas k_s t ruc t条目的指针---被用于记录正在运行的进程。cu rr e n t仅能通

第 2 页共

9 页

过在ke rn e l/s c he d.c中的调度程序来改变。然而,由于所有的进程都必须访问它,所以使用了宏f o r_ea c h_tas k。当系统负荷很轻时,它要比数组的顺序扫描快得多。

进程总是运行于“用户模式”或“内核模式”。用户程序的主体是运行于用户模式而其中的系统调用则运行于内核模式中。在这两种执行模式中进程所用的堆栈是不一样的-- 常规的堆栈段用于用户模式,而一个固定大小的堆栈(一页,由该进程所有)则用于内核模式。内核堆栈页是从不交换出去的,因为每当一个系统调用进入时它就必须存在着。

内核中的系统调用(s y ste m c a ll s)是作为C语言函数存在的,它们的‘正规’名称是以‘s y s_’开头的。例如一个名为b ur n o u t的系统调用将调用内核函数s y s_b ur n o u t()。

系统调用机制在本手册的第三章中进行了讨论。观看在i ncl u de/l in ux/s c he d.h

中的fo r_e a c h_tas k和S ET_LI NK S能够帮助理解进程表中的列表和树结构。

创建和结束进程

un ix系统是通过fo r k()系统调用创建一个进程的,而进程的终止是通过e xi t()或收到一个信号来完成的。它们的L in ux实现位于ke rn e l/fo r k.c和ke rn e l/e xi t.c中。派生出一个进程是很容易的,所以fo r k.c程序很短并易于理解。它的主要任务是为新的进程填写数据结构。除了填写各个字段以外,相关的步骤有:

取得一个空闲内存页面来保存tas k_s t ruc t

找到一个空闲的进程槽(f in d_em pty_p r o c e ss())

为内存堆栈页ke rn e l_sta ck_pa ge取得另一个空闲的内存页面

将父辈的L DT拷贝到子进程

复制父进程的m map信息

s y s_f o r k()同样也管理文件描述符和in od e。

1.0的内核也对线程提供某些不够完善的支持,所以fo r k()系统调用对此也给出了

某些示意。内核的线程是主流内核以外的过程产品。

从一个进程中退出是比较有窍门的,因为父进程必须被通告有关任何子进程的退出。而且,一个进程可以由另外一个进程使用k il l()而退出(这些是Un i x的特性),所以除了

s y s_e xi t()之外,s y s_k il l()以及s y s_w a i t()的各种特性也存在于e xi t.c之中了。

这里不对e xi t.c的代码加以讨论---因为它一点也不令人感兴趣。为了以一致的状态退出系统,它涉及到许多细节。而P OSI X标准对于信号则是要求相当严格的,所以这里必须对其加以叙述。

执行程序

在调用了fo r k()之后,就有同一个程序的两个拷贝在运行了,通常一个程序使用e x e c()

执行另一个程序。e x e c()系统调用必须定位该执行文件的二进制映像,加载并执行它。词语‘加载’并不一定意味着“将二进制映像拷贝进内存”,因为L in ux支持按需加载。e x e c()的L in ux实现支持不同的二进制格式。这是通过li nu x_b in fm t结构来达到的,其中内嵌了两个指向函数的指针--一个是用于加载可执行文件的,另一个用于加载库函数,每种二进制格式都实现有这两个函数。共享库的加载是在e x e c()同一个源程序中实现的,但我们只讨论e x e c()本身。U n i x系统提供了六种e x e c()函数。除了一个以外,所有都是以库函数的形式实现的,并且,L in ux内核是单独实现s y s_e x e c ve()调用的。它执行一个非常简单的任务:加载可执行文件的头部,并试着去执行它。如果头两个字节是“#!”,那么就会解析该可执行文件的第一行并调用一个解释器来执行它,否则的话,就会顺序地试用各个注册过的二进制格式。L i nu x本身的格式是由f s/e x e c.c直接支持的,并且相关的函数是

第 3 页共

9 页

l oa d_ao u t_b in a r y和l oad_a o u t_li b r a r y。对于二进制,函数将加载一个“a.o u t”可执行

文件并以使用mm ap()加载磁盘文件或调用r ead_e x e c()而结束。前一种方法使用了L in ux

的按需加载机理,在程序被访问时使用出错加载方式(fa ul t-i n)加载程序页面,而后一种

方式是在主机文件系统不支持内存映像时(例如“m s do s”文件系统)使用的。

新近的1.1内核内嵌了一个修订的m s do s文件系统,它支持mm ap()。而且li nu x_b in fmt结构已是一个链表而不是一个数组了,以允许以一个内核模块的方式加载一

个新的二进制格式。最后,结构的本身也已经被扩展成能够访问与格式相关的核心转储程序

了。

访问文件系统

众所周知,文件系统是U n i x系统中最为基本的资源了,它如此的基本和普遍存在以至于它需要一个更为便利的名字--我将忠于标准的称呼简单地称之为“f s”。

我将假设读者早已知道基本的Uni x文件系统的原理--访问(权限)许可、i节点(i n od e)、超级块、加载(mo un t)和卸载(u mo un t)文件系统。这些概念在标准的U nix文献中由比我聪明的作

者给出了很好的解释,所以我就不重复他们的工作并且我将只专注于有关Li nu x方面的问

题。

早期的Un i x通常只支持一个文件系统(f s)类型,它的代码散布于整个内核中,现今的实现是在内核和f s之间使用一个标准的接口,以便于在不同的体系结构中进行数据

的交换。Li nu x本身提供了一个标准层以在内核和每种f s模块之间传递数据。这个接口

层称为V FS,即“虚拟文件系统”("v ir t u a l f il e s y s tem")。

因而文件系统的代码被分割成了两层:上层是关于内核表格的管理和数据结构的,而低层是由与各文件系统相关的函数集构成的,并且是由V FS数据结构进行调用的。所有与文件系统独立的资料都位于f s/*.c文件中。它们涉及如下的问题:

?管理缓冲寄存器(b u ff e r.c);

?对f cn t l()和i o c t l()系统调用作出响应(f cn t l.c和i o c t l.c);

?在i n od e和缓冲区上映射管道和f i fo(f i fo.c,p i pe.c);

?管理文件-和in od e -表(f il e_tab l e.c,i node.c);

?锁定和解锁文件和记录(l o c k.c);

?将名称映射到i n od e(n am e i.c,op e n.c);

?实现错综复杂的s e l e c t()函数(s e l e c t.c);

?提供信息(s ta t.c);

?加载和卸载文件系统(s u pe r.c);

?使用e x e c()执行可执行程序以及转储核心程序(e x e c.c);

?加载各种二进制格式(b in_f mt*.c,如上面所述)。

而V FS接口则由一组相对比较高层次的操作组成,并从与文件系统独立的代码中调用而实际上是由每种文件系统类型执行的。最为相关的数据结构是in od e_op e r at i o ns和

f il e_op e r at i o ns,尽管它们不是独自存在的:同样存在着其它一些数据结构。它们都定义

在i nc lu de/li nu x/f s.h文件中。

到实际文件系统的内核入口点是数据结构f il e_s y ste m_ty pe。f il e_s y ste m_ty pe s的一个数组包含在f s/f il e s y ste m s.c中,并且每当发出了一个加载(mo un t)命令时都会引用它。然

后,相应f s类型的函数r ea d_su pe r就负责填写结构su pe r_b l o c k的一个项,而该项又内

嵌了结构su pe r_s t ruc t和结构ty pe_s b_in fo。前者为当前的f s类型提供了指向一般f s操

作的指针,而后者对相应f s类型内嵌了特定的信息。

第 4 页共

9 页

Li nu x内核源代码漫游创建时间:2001-10-1121时13分文件系统类型数组已经转换成了一个链表,以允许用内核模块的形式加载新的f s

类型。函数(un-)r eg is te r_f il e s y s tem代码包含在f s/su pe r.c中。

一个文件系统类型的快速剖析

一个文件系统类型的任务是执行用于映射相应高层V FS操作到物理介质(磁盘、网络等等)的低层任务。V FS接口有足够的灵活性来支持传统的Un i x文件系统和外来的象m s do s和u m s do s文件系统类型。

每一个f s类型除了它自己的源代码目录以外,是由下列各项组成的:

?f il e_s y ste m s[]数组中的一个条目(项)(f s/f il e s y ste m s.c);

?超级块(su pe r b l o c k)的in cl u de文件(in c l u de/li nu x/ty pe_f s_s b.h);

?i节点(i node)的in cl u de文件(i nc l u de/l in ux/ty pe_f s_i.h);

?普通自己专用的i nc lu de文件(i nc l u de/l in ux/ty pe_f s.h);

?in cl u de/l inu x.f s.h中的两行#in cl u de,以及在结构s u pe r_b l o c k和i n od e中的

条目。

对于特定f s类型自己的目录,包含有所有的实际代码、in od e和数据的管理程序。

本手册中有关p r o c f s的章节,揭示了所有有关那种f s类型的低层代码和V FS接

口。在阅读过那个章节之后,f s/p r o c f s中的源代码就显得非常容易理解了。现在我们来观察V FS机制的内部工作情况,并以m i n i x文件系统的代码作为一个实际例子。我选择m in ix类型是因为它比较短小但却是完整的;而且,Li nu x中的所有其它的

f s类型都衍生于它。在最近Li nu x安装中的事实上的标准文件系统类型e x t2,要比它复

杂得多,对e x t2这个文件系统的探索就留给聪明的读者作为一个练习了。

当一个m in ix-f s被加载后,m in ix_r e ad_su pe r就会把从被加载的设备中读取的数据添入s u pe r_b l o c k数据结构中。此时,该结构中的s_op域将保留有一个指向m ini x_s op s的指针,该指针将被一般文件系统代码用于分派超级块的操作。

在全局系统树结构中链接新加载的f s依赖于下列各数据项(假设s b是超级块数据结构,而d ir_i是指向加载点的in od e的指针):

?s b->s_m o un te d指向被加载文件系统的根目录i节点(MI N I X_RO O T_I N O);

?d ir_i->i_m o un t保存有s b->s_m o un ted;

?s b->s_c ove r ed保存有d ir_i

卸载操作将最终通过do_u mo un t来执行,而它会依次调用m ini x_p u t_su pe r。每当访问一个文件时,m in ix_r ea d_in od e就会开始执行;它会使用m in ix_in od e各字段中的数据填写

系统范围的i n od e数据结构。in od e->i_o p字段是依照in od e->i_m od e来填写的,它将负责该文件的任何其它操作。上述m in ix函数的代码可以从f s/m in ix/i n od e.c

中找到。

in od e_op e r at i o ns数据结构是用于把in od e操作分派给特定f s类型的内核函数;该数据结构的第一项是一个指向f il e_ope r at i o ns项的指针,它等同于数据管理的i_o p。m in ix 文件系统类型允许有i n od e操作集中的三种方式(用于目录、文件和符号链接)和文件操作集中的两种(符号链接不需要文件操作)。

目录操作(仅m in ix_r ead d ir)位于f s/m in ix/d ir.c中;文件操作(读r ea d和写w ri te)位于f s/m i nix/f il e.c中而符号操作(读取并跟随着链)位于f s/m in ix/s ym li n k.c。

m i n i x源代码目录中的其余部分用于实现以下任务:

?b i tm ap.c用于管理i节点与块的分配和释放(而e x t2文件系统却有两个不同的

代码文件);

第 5 页共

9 页


如何安装Linux内核源代码

如何获取Linux内核源代码 下载Linux内核当然要去官方网站了,网站提供了两种文件下载,一种是完整的Linux 内核,另一种是内核增量补丁,它们都是tar归档压缩包。除非你有特别的原因需要使用旧版本的Linux内核,否则你应该总是升级到最新版本。 使用Git 由Linus领头的内核开发队伍从几年前就开始使用Git版本控制系统管理Linux内核了(参考阅读:什么是Git?),而Git项目本身也是由Linus创建的,它和传统的CVS不一样,Git是分布式的,因此它的用法和工作流程很多开发人员可能会感到很陌生,但我强烈建议使用Git下载和管理Linux内核源代码。 你可以使用下面的Git命令获取Linus内核代码树的最新“推送”版本: $ git clone git://https://www.doczj.com/doc/946251040.html,/pub/scm/linux/kernel/git/torvalds/linux-2.6.git 然后使用下面的命令将你的代码树与Linus的代码树最新状态同步: $ git pull 安装内核源代码 内核包有GNU zip(gzip)和bzip2格式。Bzip2是默认和首选格式,因为它的压缩比通常比gzip更好,bzip2格式的Linux内核包一般采用linux-x.y.z.tar.bz2形式的文件名,这里的x.y.z是内核源代码的具体版本号,下载到源代码包后,解压和抽取就很简单了,如果你下载的是bzip2包,运行: $ tar xvjf linux-x.y.z.tar.bz2 如果你下载的是gzip包,则运行: $ tar xvzf linux-x.y.z.tar.gz 无论执行上面哪一个命令,最后都会将源代码解压和抽取到linux-x.y.z目录下,如果你使用Git下载和管理内核源代码,你不需要下载tar包,只需要运行git clone命令,它就会自动下载和解压。 内核源代码通常都会安装到/usr/src/linux下,但在开发的时候最好不要使用这个源代码树,因为针对你的C库编译的内核版本通常也链接到这里的。 应用补丁

Linux操作系统源代码详细分析

linux源代码分析:Linux操作系统源代码详细分析 疯狂代码 https://www.doczj.com/doc/946251040.html,/ ?:http:/https://www.doczj.com/doc/946251040.html,/Linux/Article28378.html 内容介绍: Linux 拥有现代操作系统所有功能如真正抢先式多任务处理、支持多用户内存保护虚拟内存支持SMP、UP符合POSIX标准联网、图形用户接口和桌面环境具有快速性、稳定性等特点本书通过分析Linux内核源代码充分揭示了Linux作为操作系统内核是如何完成保证系统正常运行、协调多个并发进程、管理内存等工作现实中能让人自由获取系统源代码并不多通过本书学习将大大有助于读者编写自己新 第部分 Linux 内核源代码 arch/i386/kernel/entry.S 2 arch/i386/kernel/init_task.c 8 arch/i386/kernel/irq.c 8 arch/i386/kernel/irq.h 19 arch/i386/kernel/process.c 22 arch/i386/kernel/signal.c 30 arch/i386/kernel/smp.c 38 arch/i386/kernel/time.c 58 arch/i386/kernel/traps.c 65 arch/i386/lib/delay.c 73 arch/i386/mm/fault.c 74 arch/i386/mm/init.c 76 fs/binfmt-elf.c 82 fs/binfmt_java.c 96 fs/exec.c 98 /asm-generic/smplock.h 107 /asm-i386/atomic.h 108 /asm- i386/current.h 109 /asm-i386/dma.h 109 /asm-i386/elf.h 113 /asm-i386/hardirq.h 114 /asm- i386/page.h 114 /asm-i386/pgtable.h 115 /asm-i386/ptrace.h 122 /asm-i386/semaphore.h 123 /asm-i386/shmparam.h 124 /asm-i386/sigcontext.h 125 /asm-i386/siginfo.h 125 /asm-i386/signal.h 127 /asm-i386/smp.h 130 /asm-i386/softirq.h 132 /asm-i386/spinlock.h 133 /asm-i386/system.h 137 /asm-i386/uaccess.h 139 //binfmts.h 146 //capability.h 147 /linux/elf.h 150 /linux/elfcore.h 156 /linux/errupt.h 157 /linux/kernel.h 158 /linux/kernel_stat.h 159 /linux/limits.h 160 /linux/mm.h 160 /linux/module.h 164 /linux/msg.h 168 /linux/personality.h 169 /linux/reboot.h 169 /linux/resource.h 170 /linux/sched.h 171 /linux/sem.h 179 /linux/shm.h 180 /linux/signal.h 181 /linux/slab.h 184 /linux/smp.h 184 /linux/smp_lock.h 185 /linux/swap.h 185 /linux/swapctl.h 187 /linux/sysctl.h 188 /linux/tasks.h 194 /linux/time.h 194 /linux/timer.h 195 /linux/times.h 196 /linux/tqueue.h 196 /linux/wait.h 198 init/.c 198 init/version.c 212 ipc/msg.c 213 ipc/sem.c 218 ipc/shm.c 227 ipc/util.c 236 kernel/capability.c 237 kernel/dma.c 240 kernel/exec_do.c 241 kernel/exit.c 242 kernel/fork.c 248 kernel/info.c 255 kernel/itimer.c 255 kernel/kmod.c 257 kernel/module.c 259 kernel/panic.c 270 kernel/prk.c 271 kernel/sched.c 275 kernel/signal.c 295 kernel/softirq.c 307 kernel/sys.c 307 kernel/sysctl.c 318 kernel/time.c 330 mm/memory.c 335 mm/mlock.c 345 mm/mmap.c 348 mm/mprotect.c 358 mm/mremap.c 361 mm/page_alloc.c 363 mm/page_io.c 368 mm/slab.c 372 mm/swap.c 394 mm/swap_state.c 395 mm/swapfile.c 398 mm/vmalloc.c 406 mm/vmscan.c 409

关于Linux 内核中五个主要子系统的介绍

关于Linux 内核中五个主要子系统的介绍 发布时间:2008.01.02 06:23来源:赛迪网作者:sixth 1.进程调度(SCHED):控制进程对CPU的访问。当需要选择下一个进程运行时,由调度程序选择最值得运行的进程。可运行进程实际上是仅等待CPU资源的进程,如果某个进程在等待其它资源,则该进程是不可运行进程。Linux使用了比较简单的基于优先级的进程调度算法选择新的进程。 2.内存管理(MM)允许多个进程安全的共享主内存区域。Linux的内存管理支持虚拟内存,即在计算机中运行的程序,其代码,数据,堆栈的总量可以超过实际内存的大小,操作系统只是把当前使用的程序块保留在内存中,其余的程序块则保留在磁盘中。必要时,操作系统负责在磁盘和内存间交换程序块。内存管理从逻辑上分为硬件无关部分和硬件有关部分。硬件无关部分提供了进程的映射和逻辑内存的对换;硬件相关的部分为内存管理硬件提供了虚拟接口。 3.虚拟文件系统(VirtualFileSystem,VFS)隐藏了各种硬件的具体细节,为所有的设备提供了统一的接口,VFS提供了多达数十种不同的文件系统。虚拟文件系统可以分为逻辑文件系统和设备驱动程序。逻辑文件系统指Linux所支持的文件系统,如ext2,fat等,设备驱动程序指为每一种硬件控制器所编写的设备驱动程序模块。 4.网络接口(NET)提供了对各种网络标准的存取和各种网络硬件的支持。网络接口可分为网络协议和网络驱动程序。网络协议部分负责实现每一种可能的网络传输协议。网络设备驱动程序负责与硬件设备通讯,每一种可能的硬件设备都有相应的设备驱动程序。 5.进程间通讯(IPC) 支持进程间各种通信机制。处于中心位置的进程调度,所有其它的子系统都依赖它,因为每个子系统都需要挂起或恢复进程。一般情况下,当一个进程等待硬件操作完成时,它被挂起;当操作真正完成时,进程被恢复执行。例如,当一个进程通过网络发送一条消息时,网络接口需要挂起发送进程,直到硬件成功地完成消息的发送,当消息被成功的发送出去以后,网络接口给进程返回一个代码,表示操作的成功或失败。其他子系统以相似的理由依赖于进程调度。

linux内核IMQ源码实现分析

本文档的Copyleft归wwwlkk所有,使用GPL发布,可以自由拷贝、转载,转载时请保持文档的完整性,严禁用于任何商业用途。 E-mail: wwwlkk@https://www.doczj.com/doc/946251040.html, 来源: https://www.doczj.com/doc/946251040.html,/?business&aid=6&un=wwwlkk#7 linux2.6.35内核IMQ源码实现分析 (1)数据包截留并重新注入协议栈技术 (1) (2)及时处理数据包技术 (2) (3)IMQ设备数据包重新注入协议栈流程 (4) (4)IMQ截留数据包流程 (4) (5)IMQ在软中断中及时将数据包重新注入协议栈 (7) (6)结束语 (9) 前言:IMQ用于入口流量整形和全局的流量控制,IMQ的配置是很简单的,但很少人分析过IMQ的内核实现,网络上也没有IMQ的源码分析文档,为了搞清楚IMQ的性能,稳定性,以及借鉴IMQ的技术,本文分析了IMQ的内核实现机制。 首先揭示IMQ的核心技术: 1.如何从协议栈中截留数据包,并能把数据包重新注入协议栈。 2.如何做到及时的将数据包重新注入协议栈。 实际上linux的标准内核已经解决了以上2个技术难点,第1个技术可以在NF_QUEUE机制中看到,第二个技术可以在发包软中断中看到。下面先介绍这2个技术。 (1)数据包截留并重新注入协议栈技术

(2)及时处理数据包技术 QoS有个技术难点:将数据包入队,然后发送队列中合适的数据包,那么如何做到队列中的数

激活状态的队列是否能保证队列中的数据包被及时的发送吗?接下来看一下,激活状态的队列的 证了数据包会被及时的发送。 这是linux内核发送软中断的机制,IMQ就是利用了这个机制,不同点在于:正常的发送队列是将数据包发送给网卡驱动,而IMQ队列是将数据包发送给okfn函数。

Linux源代码下载

1. 课程设计题目:下载某个版本的linux源代码,生成一个定制的linux操作系统,完成后该系统可以用来作为启动系统使用。 2.如何做的问题? 内核版本要编译一个最新的内核,您需要首先下载它的源代码在您下载内核的源代码前,您要知道到您要找什么。首先要问您自己的问题是-- 您需要一份稳定的还是测试版的内核?稳定版内核通常版本号第二位用偶数数字 -- 例如, 2.0.38、2.2.15、2.2.1 8 和2.4.1 是被认为是“稳定”的内核(分别由于其包含 0、2、2 和4)。如果您想尝试测试版内核,您通常需要找那些版本号第二位是奇数的号码又最高的内核。例如,2.3.99 和 2.1.38都是测试版内核(分别由于其包含 3 和 1)。 内核版本历史 2.2 系列的内核被认为是较新而且稳定的内核。如果"较新"和"稳定"是您想要的,查找一个版本号的第三位是最高的2.2 内核(2.2.16 是目前最新的版本)。当 2.2 系列的内核仍在开发中,2.3 系列已经开始了。这个系列是作为将被集成到 2.4稳定版系列的新功能和高级功能的测试版。2.3 系列已经到了 2.3.99,其开发已经停止。开发人员已经开始着手2.4.0。如果您喜欢冒险使用最最新的技术,您可能想使用可以找到的最新的 2.4 系列内核。

2.4 版内核警告信息 Once a real 2.4 series kernel comes out(like 2.4.0), don't assume that the kernel is ready for use on a mission-critical system like a server. Even though 2.4 is supposed tobe a stable series, early 2.4 kernels ar e likely to be not quite up tosnuff. As is often the case i n the computer industry, the first version o f anythin g can have fairly sizable bugs. While this may not be a problem i f you're testing the kernel on your home workstation, it is a risk you may want to avoid when you machine provides val uable services to others. 下载内核 如果您只是想编译一个您已安装内核的新版本(例如,实现 SMP 支持),那不需要下载任何代码 -- 跳过此部分继续下一屏。 您可以在https://www.doczj.com/doc/946251040.html,/pub/linux/kernel上找到内核代码。当您进入到那后,您将发现内核的源代码按内核版本(v2.2、v 2.3等),被组织到多个不同的目录中。在每个目录中,您将发现文件被冠以"linux-x.y.z.tar.gz"和"linux-x.y.z.tar.bz2"。这些就是Linux 内核的源代码。您也将看到冠以 "patch-x.y.z.gz" 和"pa tch-x.y.z.bz2"的文件。这些是用来更新前面完整的内核源代码的补丁包。如果您希望编译一个新的内核版本,您将需要下载这些"linu x"文件其中之一。

读Linux内核源代码

Linux内核分析方法 Linux的最大的好处之一就是它的源码公开。同时,公开的核心源码也吸引着无数的电脑爱好者和程序员;他们把解读和分析Linux的核心源码作为自己的最大兴趣,把修改Linux源码和改造Linux系统作为自己对计算机技术追求的最大目标。 Linux内核源码是很具吸引力的,特别是当你弄懂了一个分析了好久都没搞懂的问题;或者是被你修改过了的内核,顺利通过编译,一切运行正常的时候。那种成就感真是油然而生!而且,对内核的分析,除了出自对技术的狂热追求之外,这种令人生畏的劳动所带来的回报也是非常令人着迷的,这也正是它拥有众多追随者的主要原因: ?首先,你可以从中学到很多的计算机的底层知识,如后面将讲到的系统的引导和硬件提供的中断机制等;其它,象虚拟存储的实现机制,多任务机制,系统保护机制等等,这些都是非都源码不能体会的。 ?同时,你还将从操作系统的整体结构中,体会整体设计在软件设计中的份量和作用,以及一些宏观设计的方法和技巧:Linux的内核为上层应用提供一个与具体硬件不相关的平台; 同时在内核内部,它又把代码分为与体系结构和硬件相关的部分,和可移植的部分;再例如,Linux虽然不是微内核的,但他把大部分的设备驱动处理成相对独立的内核模块,这样减小了内核运行的开销,增强了内核代码的模块独立性。 ?而且你还能从对内核源码的分析中,体会到它在解决某个具体细节问题时,方法的巧妙:如后面将分析到了的Linux通过Botoom_half机制来加快系统对中断的处理。 ?最重要的是:在源码的分析过程中,你将会被一点一点地、潜移默化地专业化。一个专业的程序员,总是把代码的清晰性,兼容性,可移植性放在很重要的位置。他们总是通过定义大量的宏,来增强代码的清晰度和可读性,而又不增加编译后的代码长度和代码的运行效率; 他们总是在编码的同时,就考虑到了以后的代码维护和升级。甚至,只要分析百分之一的代码后,你就会深刻地体会到,什么样的代码才是一个专业的程序员写的,什么样的代码是一个业余爱好者写的。而这一点是任何没有真正分析过标准代码的人都无法体会到的。 然而,由于内核代码的冗长,和内核体系结构的庞杂,所以分析内核也是一个很艰难,很需要毅力的事;在缺乏指导和交流的情况下,尤其如此。只有方法正确,才能事半功倍。正是基于这种考虑,作者希望通过此文能给大家一些借鉴和启迪。 由于本人所进行的分析都是基于2.2.5版本的内核;所以,如果没有特别说明,以下分析都是基于i386单处理器的2.2.5版本的Linux内核。所有源文件均是相对于目录/usr/src/linux的。 方法之一:从何入手 要分析Linux内核源码,首先必须找到各个模块的位置,也即要弄懂源码的文件组织形式。虽然对于有经验的高手而言,这个不是很难;但对于很多初级的Linux爱好者,和那些对源码分析很

Linux内核源代码阅读与工具介绍

Linux的内核源代码可以从很多途径得到。一般来讲,在安装的linux系统下,/usr/src/linux 目录下的东西就是内核源代码。另外还可以从互连网上下载,解压缩后文件一般也都位于linux目录下。内核源代码有很多版本,目前最新的版本是2.2.14。 许多人对于阅读Linux内核有一种恐惧感,其实大可不必。当然,象Linux内核这样大而复杂的系统代码,阅读起来确实有很多困难,但是也不象想象的那么高不可攀。只要有恒心,困难都是可以克服的。任何事情做起来都需要有方法和工具。正确的方法可以指导工作,良好的工具可以事半功倍。对于Linux内核源代码的阅读也同样如此。下面我就把自己阅读内核源代码的一点经验介绍一下,最后介绍Window平台下的一种阅读工具。 对于源代码的阅读,要想比较顺利,事先最好对源代码的知识背景有一定的了解。对于linux内核源代码来讲,基本要求是:⑴操作系统的基本知识;⑵对C语言比较熟悉,最好要有汇编语言的知识和GNU C对标准C的扩展的知识的了解。另外在阅读之前,还应该知道Linux内核源代码的整体分布情况。我们知道现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序、网络等组成。看一下Linux内核源代码就可看出,各个目录大致对应了这些方面。Linux内核源代码的组成如下(假设相对于linux目录): arch这个子目录包含了此核心源代码所支持的硬件体系结构相关的核心代码。如对于X86平台就是i386。 include这个目录包括了核心的大多数include文件。另外对于每种支持的体系结构分别有一个子目录。 init此目录包含核心启动代码。 mm此目录包含了所有的内存管理代码。与具体硬件体系结构相关的内存管理代码位于arch/*/mm目录下,如对应于X86的就是arch/i386/mm/fault.c。 drivers系统中所有的设备驱动都位于此目录中。它又进一步划分成几类设备驱动,每一种也有对应的子目录,如声卡的驱动对应于drivers/sound。 ipc此目录包含了核心的进程间通讯代码。 modules此目录包含已建好可动态加载的模块。 fs Linux支持的文件系统代码。不同的文件系统有不同的子目录对应,如ext2文件系统对应的就是ext2子目录。 kernel主要核心代码。同时与处理器结构相关代码都放在arch/*/kernel目录下。 net核心的网络部分代码。里面的每个子目录对应于网络的一个方面。 lib此目录包含了核心的库代码。与处理器结构相关库代码被放在arch/*/lib/目录下。

Linux内核编码风格(编程代码风格推荐)

这是翻译版本,英文原版是linux源码Documentation文件夹下的CodingStyle 一个良好风格的程序看起来直观、美观,便于阅读,还能有助于对程序的理解,特别在代码量比较大情况下更显现编码素质的重要性。相反没有良好的风格的代码读起来难看、晦涩,甚至有时候一个括号没对齐就能造成对程序的曲解或者不理解。我曾经就遇见过这样的情况,花费了很多不必要的时间在程序的上下文对照上,还debug了半天没理解的程序。后来直接用indent -kr -i8给他转换格式来看了。特此转过来一个关于代码风格的帖子分享一下~ Linux内核编码风格 这是一份简短的,描述linux内核首选编码风格的文档。编码风格是很个人化的东西,而且我也不愿意把我的观点强加给任何人,不过这里所讲述的是我必须要维护的代码所遵守的风格,并且我也希望绝大多数其他代码也能遵守这个风格。所以请至少考虑一下本文所述的观点。 首先,我建议你打印一份GNU的编码规范,然后不要读它。烧掉它,这是一个很高调的具有象征意义的姿态。 Anyway, here goes: 第一章:缩进 制表符是8个字符,所以缩进也是8个字符。有些异端运动试图将缩进变为4(乃至2)个字符深,这跟尝试着将圆周率PI的值定义为3没什么两样。 理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕连续看了20小时之后,你将会发现大一点的缩进将会使你更容易分辨缩进。 现在,有些人会抱怨8个字符的缩进会使代码向右边移动的太远,在80个字符的终端屏幕上就很难读这样的代码。这个问题的答案是,如果你需要3级以上的缩进,不管缩进深度如何你的代码已经有问题了,应该修正你的程序。 简而言之,8个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太深的时候可以向你提出告警。请留意这个警告。 在switch语句中消除多级缩进的首选的方式是让“switch”和从属于它的“case”标签对 齐于同一列,而不要“两次缩进”“case”标签。比如: switch (suffix) { case 'G': case 'g': mem <<= 30;

linux源代码分析实验报告格式

linux源代码分析实验报告格式

Linux的fork、exec、wait代码的分析 指导老师:景建笃 组员:王步月 张少恒 完成日期:2005-12-16

一、 设计目的 1.通过对Linux 的fork 、exec 、wait 代码的分析,了解一个操作系统进程的创建、 执行、等待、退出的过程,锻炼学生分析大型软件代码的能力; 2.通过与同组同学的合作,锻炼学生的合作能力。 二、准备知识 由于我们选的是题目二,所以为了明确分工,我们必须明白进程的定义。经过 查阅资料,我们得知进程必须具备以下四个要素: 1、有一段程序供其执行。这段程序不一定是进程专有,可以与其他进程共用。 2、有起码的“私有财产”,这就是进程专用的系统堆栈空间 3、有“户口”,这就是在内核中有一个task_struct 结构,操作系统称为“进程控制 块”。有了这个结构,进程才能成为内核调度的一个基本单位。同时,这个结构又 是进程的“财产登记卡”,记录着进程所占用的各项资源。 4、有独立的存储空间,意味着拥有专有的用户空间:进一步,还意味着除前述的 系统空间堆栈外,还有其专用的用户空间堆栈。系统为每个进程分配了一个 task_struct 结构,实际分配了两个连续的物理页面(共8192字节),其图如下: Struct task_struct (大约1K) 系统空间堆栈 (大约7KB )两个 连续 的物 理页 面 对这些基本的知识有了初步了解之后,我们按老师的建议,商量分工。如下: 四、 小组成员以及任务分配 1、王步月:分析进程的创建函数fork.c ,其中包含了get_pid 和do_fork get_pid, 写出代码分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作 比例35%。 2、张少恒:分析进程的执行函数exec.c,其中包含了do_execve 。写出代码分析结 果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例35% 。 3、余波:分析进程的退出函数exit.c,其中包含了do_exit 、sys_wait4。写出代码 分析结果,并画出流程图来表示相关函数之间的相互调用关系。所占工作比例30% 。 五、各模块分析: 1、fork.c 一)、概述 进程大多数是由FORK 系统调用创建的.fork 能满足非常高效的生灭机制.除了 0进程等少数一,两个进程外,几乎所有的进程都是被另一个进程执行fork 系统调 用创建的.调用fork 的进程是父进程,由fork 创建的程是子进程.每个进程都有一

Linux源代码分析_存储管理

文章编号:1004-485X (2003)03-0030-04 收稿日期:2003-05-10 作者简介:王艳春,女(1964 ),副教授,主要从事操作系统、中文信息处理等方面的研究工作。 Linux 源代码分析 存储管理 王艳春 陈 毓 葛明霞 (长春理工大学计算机科学技术学院,吉林长春130022) 摘 要:本文剖析了Linux 操作系统的存储管理机制。给出了Linux 存储管理的特点、虚存的实现方法,以及主要数据结构之间的关系。 关键词:Linux 操作系统;存储管理;虚拟存储中图分类号:T P316 81 文献标识码:A Linux 操作系统是一种能运行于多种平台、源代码公开、免费、功能强大、与Unix 兼容的操作系统。自其诞生以来,发展非常迅速,在我国也受到政府、企业、科研单位、大专院校的重视。我们自2000年开始对Linux 源代码(版本号是Linux 2 2 16)进行分析,首先剖析了进程管理和存储管理部分,本文是有关存储管理的一部分。主要介绍了Linux 虚存管理所用到的数据结构及其相互间的关系,据此可以更好地理解其存储管理机制,也可以在此基础上对其进行改进或在此后的研究中提供借鉴作用。作为一种功能强大的操作系统,Linux 实现了以虚拟内存为主的内存管理机制。即能够克服物理内存的局限,使用户进程在透明方式下,拥有比实际物理内存大得多的内存。本文主要阐述了Linux 虚存管理的基本特点和主要实现技术,并分析了Linux 虚存管理的主要数据结构及其相互关系。 1 Lin ux 虚存管理概述 Linux 的内存管理采用虚拟页式管理,使用多级页表,动态地址变换。进程在运行过程中可以动态浮动和扩展,为用户提供了透明的、灵活有效的内存使用方式。 1)32 bit 虚拟地址 在Linux 中,进程的4GB 虚存需通过32 bit 地址进行寻址。Linux 中虚拟地址与线性地址为同一概念,虚拟地址被分成3个子位段,而大小为4k,如图1所示。 2)Linux 的多级页表结构 图1 32位虚拟地址 标准的Linux 的虚存页表为三级页表,依次为页目录(Pag e Directory PGD)、中间页目录(Pag e Middle Directory PMD )、页表(Page Table PT E )。在i386机器上Linux 的页表结构实际为两级,PGD 和PMD 页表是合二为一的。所有有关PMD 的操作关际上是对PGD 的操作。所以源代码中形如*_pgd _*()和*_pmd_*()函数实现的功能也是一样的。 页目录(PGD)是一个大小为4K 的表,每一个进程只有一个页目录,以4字节为一个表项,分成1024个表项(或称入口点),表项的索引即为32位虚拟地址的页目录,该表项的值为所指页表的起始地址。页表(PTE)的每一个入口点的值为此表项所指的一页框(page frame),页表项的索引即为32位虚拟地址中的页号。页框(page reame)并不是物理页,它指的是虚存的一个地址空间。 3) 页表项的格式 图2 Linux 中页目录项和页表项格式 4)动态地址映射 Linux 虚存采用动态地址映射方式,即进程的地址空间和存储空间的对应关系是在程序的执行过 第26卷第3期长春理工大学学报 Vol 26N o 32003年9月 Journal of Changchun University of Science and T echnology Sep.2003

Linux内核版本号及源代码目录树结构

Linux 内核版本号及源代码目录树结构 一、linux内核版本号的命名机制 Linux内核版本有两种:稳定版和开发版。稳定的内核具有工业级的强度,可以广泛地应用和部署。新的稳定内核相对于较旧的只是修正一些bug或加入一些新的驱动程序。而开发版内核由于要试验各种解决方案,所以变化很快。这两种版本是相互关联,相互循环的。 Linux内核的命名机制: num.num.num 其中第一个数字是主版本号,第二个数字是次版本号,第三个数字是修订版本号。如果次版本号是偶数,那么该内核就是稳定版的;若是奇数,则是开发版的。头两个数字合在一齐可以描述内核系列。如稳定版的2.6.0,它是2.6版内核系列。最新的内核源代码可以在https://www.doczj.com/doc/946251040.html,以tar包或者增量补丁的形式下载.。 Linux还有各种发行版本,除了最熟悉的Redhat,Debian,Bluepoint,红旗,还有 Slackware,Mandarke,Turbo。 二、linux源代码目录树结构 Linux用来支持各种体系结构的源代码包含大约4500个C语言程序,存放在270个左右的子目录下,总共大约包含200万行代码,大概占用58MB磁盘空间。 在阅读源码之前,还应知道Linux内核源码的整体分布情况。现代的操作系统一般由进程管理、内存管理、文件系统、驱动程序和网络等组成。Linux内核源码的各个目录大致与此相对应,其组成如下: arch目录包括了所有和体系结构相关的核心代码。它下面的每一个子目录都代表一种Linux支持的体系结构,例如i386就是Intel CPU及与之相兼容体系结构的子目录。PC机一般都基于此目录。 include目录包括编译核心所需要的大部分头文件,例如与平台无关的头文件在include/linux子目录下。

Linux内核源码分析方法

Linux内核源码分析方法 一、内核源码之我见 Linux内核代码的庞大令不少人“望而生畏”,也正因为如此,使得人们对Linux的了解仅处于泛泛的层次。如果想透析Linux,深入操作系统的本质,阅读内核源码是最有效的途径。我们都知道,想成为优秀的程序员,需要大量的实践和代码的编写。编程固然重要,但是往往只编程的人很容易把自己局限在自己的知识领域内。如果要扩展自己知识的广度,我们需要多接触其他人编写的代码,尤其是水平比我们更高的人编写的代码。通过这种途径,我们可以跳出自己知识圈的束缚,进入他人的知识圈,了解更多甚至我们一般短期内无法了解到的信息。Linux内核由无数开源社区的“大神们”精心维护,这些人都可以称得上一顶一的代码高手。透过阅读Linux 内核代码的方式,我们学习到的不光是内核相关的知识,在我看来更具价值的是学习和体会它们的编程技巧以及对计算机的理解。 我也是通过一个项目接触了Linux内核源码的分析,从源码的分析工作中,我受益颇多。除了获取相关的内核知识外,也改变了我对内核代码的过往认知: 1.内核源码的分析并非“高不可攀”。内核源码分析的难度不在于源码本身,而在于如何使用更合适的分析代码的方式和手段。内核的庞大致使我们不能按照分析一般的demo程序那样从主函数开始按部就班的分析,我们需要一种从中间介入的手段对内核源码“各个击破”。这种“按需索取”的方式使得我们可以把握源码的主线,而非过度纠结于具体的细节。 2.内核的设计是优美的。内核的地位的特殊性决定着内核的执行效率必须足够高才可以响应目前计算机应用的实时性要求,为此Linux内核使用C语言和汇编的混合编程。但是我们都 知道软件执行效率和软件的可维护性很多情况下是背道而驰的。如何在保证内核高效的前提下提高内核的可维护性,这需要依赖于内核中那些“优美”的设计。 3.神奇的编程技巧。在一般的应用软件设计领域,编码的地位可能不被过度的重视,因为开发者更注重软件的良好设计,而编码仅仅是实现手段问题——就像拿斧子劈柴一样,不用太多的思考。但是这在内核中并不成立,好的编码设计带来的不光是可维护性的提高,甚至是代码性能的提升。 每个人对内核的了理解都会有所不同,随着我们对内核理解的不断加深,对其设计和实现的思想会有更多的思考和体会。因此本文更期望于引导更多徘徊在Linux内核大门之外的人进入Linux的世界,去亲自体会内核的神奇与伟大。而我也并非内核源码方面的专家,这么做也只是希望分享我自己的分析源码的经验和心得,为那些需要的人提供参考和帮助,说的“冠冕堂皇”一点,也算是为计算机这个行业,尤其是在操作系统内核方面贡献自己的一份绵薄之力。闲话少叙(已经罗嗦了很多了,囧~),下面我就来分享一下自己的Linix内核源码分析方法。 二、内核源码难不难? 从本质上讲,分析Linux内核代码和看别人的代码没有什么两样,因为摆在你面前的一般都不是你自己写出来的代码。我们先举一个简单的例子,一个陌生人随便给你一个程序,并要你看完源码后讲解一下程序的功能的设计,我想很多自我感觉编程能力还可以的人肯定觉得这没什么,只要我耐心的把他的代码从头到尾看完,肯定能找到答案,并且事实确实是如此。那么现在换一个假设,如果这个人是Linus,给你的就是Linux内核的一个模块的代码,你还会觉得依然那么 轻松吗?不少人可能会有所犹豫。同样是陌生人(Linus要是认识你的话当然不算,呵呵~)给 你的代码,为什么给我们的感觉大相径庭呢?我觉得有以下原因:

基于Linux内核定制X86平台的微操作系统(很完整详尽文章)

基于Linux内核定制X86平台的微操作系统摘要:1 0 前言2 0.1 Linux系统简介2 0.2 Linux的基本思想2 0.3 Linux内核2 0.4 Linux内核版本命名3 0.5 Linux文件系统3 0.6Linux内核引导4 0.7Linux系统组成4 1 平台的搭建4 1.1 硬件平台4 1.2 软件平台4 1.2.1 Ubuntu系统的下载4 1.2.2 Ubuntu系统的安装4 1.2.3 Ubuntu系统的配置4 2 Linux内核的编译5 2.1 内核的下载5 2.2 内核的定制5 2.3 内核的编译5 2.4 内核的制作6 3 BusyBox的编译6 3.1 BusyBox的下载6 3.2 BusyBox的配置6 3.3 BusyBox的编译7 4 Linux文件系统的制作7 4.1 文件系统的制作7 4.2 文件系统的配置9 4.3 文件系统的压缩7 5 Linux引导程序配置10 5.1 ISOLINUX的下载10 5.2 ISOLINUX的配置10 6 LinuxCD-ROM的制作10 7 Linux定制系统的运行11 7.1 VirtualBox下的运行11 7.2 U盘引导在X86平台下的运行12 8定制系统过程中的问题12 8.1 平台搭建中的问题12 8.2 内核编译中的问题12

8.3 BusyBox编译中的问题12 8.4 文件系统制作中的问题12 8.5 引导程序制作中的问题12 8.6 CD-ROM制作中的问题13 8.7 定制系统运行的问题13 参考13 基于Linux内核定制X86平台的微操作系统 王林强 (河南大学物理与电子学院通信专业,河南开封,475004) 摘要: Linux是一种自由和开放,用C语言和汇编语言写成,并符合POSIX标准的类Unix操作系统。并且由于其可定制、可裁剪的特性,不仅在桌面操作系统中有重要的地位,而且在手机、平板电脑、路由器和视频游戏控制台等嵌入式设备有其巨大的优势。 为了更好、更深入的了解及掌握Linux系统。本文详细的讲述并实践,如何从Linux内核源码,经过定制、裁剪、编译、制作文件系统、内核引导,iso光盘制作到最终完整的基于Linux内核定制的微操作系统。 通过基于Linux内核定制的微操作系统的制作,深入的理解Linux内核的工作原理、文件系统结构、内核引导等,从而精通嵌入式开发。 关键词: Linux;定制;嵌入式;微系统 An implementation of micro-operating system based on the x86 platform Linux kernel customization Wang Lin-qiang (School of Physics and Electronics, Henan University, Henan Kaifeng 475004, China) Abstract: Linux is a free and open, and POSIX-compliant Unix-like operating system written in C and assembly language. And can be cut because of its customizable features, not only in the desktop o perating system in an important position, and its huge advantage in the embedded devices, mobile phones, tablet PCs, routers, and video game consoles. In order to better and deeper understanding of and master Linux system. This article tells in d etail and practice, from the Linux kernel source code has been customized, cutting, compiling, pro

Linux内核中的Kconfig用法与说明

Linux内核中的Kconfig文件 本节不对内核的Kconfig文件进行深入展开,更多Kconfig语法和说明请阅读 。 内核源码树每个目录下都还包含一个Kconfig文件,用于描述所在目录源代码相关的内核配置菜单,各个目录的Kconfig文件构成了一个分布式的内核配置数据库。通过make menuconfig(make xconfig或者make gconfig)命令配置内核的时候,从Kconfig文件读取菜单,配置完毕保存到文件名为.config的内核配置文件中,供Makefile文件在编译内核时使用。 1.1.1 Kconfig基本语法 如程序清单0.1所示代码摘自文件,是一个比较典型的Kconfig 文件片段,包含了Kconfig的基本语法。 程序清单0.1drivers/char/Kconfig片段 menu "Character devices" source "drivers/tty/Kconfig" config DEVKMEM bool "/dev/kmem virtual device support" default y help Say Y here if you want to support the /dev/kmem device. The /dev/kmem device is rarely used, but can be used for certain kind of kernel debugging operations. When in doubt, say "N". …… endmenu 1.子菜单 通过menu和endmenu来定义一个子菜单,程序清单0.1所示代码定义了一个“Character devices”子菜单,子菜单在界面中用“--->”表示,如图0.1所示。 图0.1menu定义的子菜单 子菜单的菜单项则由config来定义,随后的“bool”、“default”、“help”等都是该菜单 项的属性:

Linux内核代码风格

CodingStyle/Linux内核代码风格 这是一个简短的文档,描述了linux内核的首选代码风格。代码风格是因人而异的,而且我不愿意把我的观点强加给任何人,不过这里所讲述的是我必须要维护的代码所遵守的风格,并且我也希望绝大多数其他代码也能遵守这个风格。请在写代码时至少考虑一下本文所述的风格。 首先,我建议你打印一份GNU代码规范,然后不要读它。烧了它,这是一个具有重大象征性 意义的动作。 不管怎样,现在我们开始: 第一章:缩进 制表符是8个字符,所以缩进也是8个字符。有些异端运动试图将缩进变为4(乃至2)个字符 深,这几乎相当于尝试将圆周率的值定义为3。 理由:缩进的全部意义就在于清楚的定义一个控制块起止于何处。尤其是当你盯着你的屏幕连续看了20小时之后,你将会发现大一点的缩进会使你更容易分辨缩进。 现在,有些人会抱怨8个字符的缩进会使代码向右边移动的太远,在80个字符的终端屏幕上 就很难读这样的代码。这个问题的答案是,如果你需要3级以上的缩进,不管用何种方式你的代码已经有问题了,应该修正你的程序。 简而言之,8个字符的缩进可以让代码更容易阅读,还有一个好处是当你的函数嵌套太深的时候可以给你警告。留心这个警告。 在switch语句中消除多级缩进的首选的方式是让“switch”和从属于它的“case”标签对齐于同一列,而不要“两次缩进”“case”标签。比如: switch (suffix) { case 'G': case 'g': mem <<= 30; break; case 'M': case 'm': mem <<= 20; break; case 'K': case 'k':

Linux内核源代码解读

Linux内核源代码解读!! 悬赏分:5 - 提问时间2007-1-24 16:28 问题为何被关闭 赵炯书中,Bootsect代码中有 mov ax , #BOOTSEG 等 我曾自学过80x86汇编,没有见过#的用法,在这为什么要用#? 另外, JMPI 的用法是什么?与JMP的区别是什么? 提问者: Linux探索者 - 一级 答复共 1 条 检举 系统初始化程序 boot.s 的分析 [转] 系统初始化程序 boot.s 的分析: 阚志刚,2000/03/20下午,在前人的基础之上进行整理完善 ******************************************************************************** ************** boot.s is loaded at 0x7c00 by the bios-startup routines, and moves itself out of the way to address 0x90000, and jumps there. 当PC 机启动时,Intel系列的CPU首先进入的是实模式,并开始执行位于地址0xFFF0处的代码,也就是ROM-BIOS起始位置的代码。BIOS先进行一系列的系统自检,然后初始化位于地址0的中断向量表。最后BIOS将启动盘的第一个扇区装入0x7C00(31K;0111,1100,0000,0000),并开始执行此处的代码。这就是对内核初始化过程的一个最简单的描述。 最初,Linux核心的最开始部分是用8086汇编语言编写的。当开始运行时,核心将自己装入到绝对地址0x90000(576K; 1001,0000,0000,0000,0000),再将其后的2k字节装入到地址0x90200(576.5k;1001,0000,0010,0000,0000)处,最后将核心的其余部分装入到0x10000(64k; 1,0000,0000,0000,0000). It then loads the system at 0x10000, using BIOS interrupts. Thereafter it disables all interrupts, moves the system down to 0x0000, changes to protected mode, and calls the start of system. System then must RE-initialize the protected mode in it's own tables, and enable interrupts as needed. 然后,关掉所有中断,把系统下移到0x0000(0k;0000,0000,0000,0000,0000)处,改变到保护模式,然后开始系统的运行.系统必须重新在保护模式下初始化自己的系统表格,并且打开所需的中断. NOTE 1! currently system is at most 8*65536(8*64k=512k; 1000,0000,0000,0000,0000) bytes long. This should be no problem, even in the future. I want to keep it simple. This 512 kB kernel size should be enough - in fact more would mean we'd have to move not just these start-up routines, but also do something about the cache-memory

相关主题
文本预览
相关文档 最新文档