Linux内核详细介绍了操作系统的基本知识。

Linux内核详细介绍了操作系统的基本知识。
如今,计算机的使用越来越普遍。几乎每个家庭都有电脑。计算机的运行离不开操作系统。在这里,萧边向您介绍Linux内核。
许多Linux爱好者对核心非常感兴趣,但他们帮不上忙。本文旨在介绍一种了解linux内核源代码的入门方法,而不是解释Linux复杂的内核机制。
1。核心源程序文件组织
(1)Linux核心源程序通常安装在 / usr / src / Linux,它有一个非常简单的编号约定:任何偶数的核心(数字中间)如:2.0.30是稳定分布的核心,而任何奇数如2.1.42核心一个发展的核心。
本文是基于稳定2.2.5源代码,并实现平台的第二部分是RedHat Linux 6。
(2)核心源程序的文件是按树形结构组织的。在源树的顶部,您将看到其中一些目录
拱:拱子目录包含了所有核心代码相关的架构。它的每个子目录是一个支持的架构,例如,一个子目录i386是英特尔CPU及其兼容architecture.pc机一般都是基于这个目录;
包括:包含子目录包括大多数编译核心需要的头文件,头文件是独立于平台的包括子目录 / Linux,英特尔CPU相关的头文件中包括 / asm-i386子目录,而目录是: / SCSI SCSI设备的头文件目录
init:这个目录包含核心初始化代码(注意:不是系统的引导代码),它包含两个文件,主文件C和版本C。这是研究核心工作原理的一个好的起点。
采购经理:这个目录包含了所有的内存管理代码独立于CPU的体系结构,如页式存储管理,内存的分配和释放,与建筑相关的内存管理代码位于拱 / / / *毫米,如拱 / / /毫米i386故障C.
内核:主要核心代码。这个目录中的文件实现了Linux系统的大部分内核函数。最重要的文件是计划C,与架构相关的代码在拱 / * /内核。
司机:把所有的设备驱动程序的系统;每个驱动程序占用的子目录,例如, /块是一个块设备驱动程序,如IDE(集成开发环境,C)。如果你想看到所有的设备可能包含一个文件系统初始化,你可以看看device_setup()在司机/块/ genhd.c.it不仅初始化硬盘功能,但也初始化网络,因为它需要使用网络安装NFS文件系统时。
其他目录如库:将核心代码库;网络:核心网络相关的代码;IPC:包含了进程间通信的核心代码;FS:所有的文件系统代码和各种类型的文件操作代码,每个子目录支持一个文件系统,例如,脂肪和ext2这个目录包含用于配置核心的脚本文件等脚本。
有一个依赖文件和每个目录的Makefile文件,这些文件被编译使用辅助文件,仔细阅读并依靠这两个文件之间的联系,明确每个文件的关系是非常有帮助的,但在一些目录和自述文件,这是一些注意的文件目录,也有利于我们的内核源码的理解。
2。解读真正的战斗:向内核添加一个系统调用
虽然Linux内核代码的组织和科学合理的树型结构,与功能的文件放同一目录下,使得程序更具可读性。然而,Linux内核源代码过于庞大和复杂,即使文件组织方法是非常合理的,还有很多在不同目录的关系,对核心部分的代码分析通常看到其他几个相关的文件,这些文件可能不在同一子目录。
下面是一个具体的内核分析示例。我希望通过这个例子,读者可以对Linux的内核组织有一些具体的了解,读者也可以学习一些内核的分析方法。
下面是一个分析的例子:
(1)操作平台
硬件:CPU英特尔奔腾II;
软件:RedHat Linux 6内核版本2.2.5
(2)相关内核源代码分析
引导和初始化系统:Linux系统引导的几种形式,常见的有开机启动和加载LILO,Linux(bootsect装载机),以及相应的源程序 / /拱i386启动 / BOOTSECT. S,它是编译过程的实模式,这不仅限于振幅分析。无论什么样的指导它,你必须跳弓 / / /安装i386内核的尽头。设置的主要是在实模式初始化,准备系统进入保护模式。此后,该系统实施的拱门/ / /头i386内核的(第一个实现拱 / / / i386启动压缩 /头。在压缩存储内核);头。在setup_idt汇编程序定义的,它是负责日256建立一个IDT(中断描述符表),该表包含所有地址和中断入口的抑郁症,包括入口地址系统调用的总控制程序system_call.of课程,除此之外,头,有做一些其他的初始化工作。
第一asmlinkage无效__init start_kernel内核运行后系统初始化(void)定义在/ usr / / / SRC Linux init /主。C,美其名曰usr / / /弓型Linux i386 / / /内核C函数void __init trap_init陷阱。(void)每个入口地址自和中断服务程序设置IDT表,系统调用控制中断服务程序system_cal节目之一;无效__init trap_init(void)通过调用宏set_system_gate功能(syscall_vector,system_call),入口系统的呼叫控制程序挂在0x80中断。
其中,syscall_vectr是常数定义在0x80 / usr / / /弓型Linux i386 / / /内核的IRQ。H,和system_call是入口地址中断主控制程序。中断主控制程序是在/ usr / / /弓型Linux i386 / / /进入内核汇编语言定义。S.
中断控制程序主要负责执行系统调用之前保存的检验,当前的调用是合法的,并根据系统调用向量,使处理器跳转到入口是存储在sys_call_table表中相应的服务例程,返回从售后服务系统恢复情况下,处理器状态过程返回到用户程序。
系统调用向量在/ usr / / /包括Src Linux / asm-386 / unistd定义。H,在/ usr / / /弓型Linux i386 / / /进入内核定义sys_call_table。S,还定义了用户编程接口系统调用在/ usr / / /包括Linux src / / unistd asm-386。H.
可以看出,Linux的系统调用也像int 21h中断服务的DOS系统,大型0x80中断作为一般的入境,然后去入口地址各种中断服务程序保存在sys_call_table表,提供各种中断服务。
提供源代码分析,添加一个系统调用必须在sys_call_table表添加一个项目,和入口地址保存在服务自己的例程,然后重新编译内核,当然,系统服务程序是必不可少的。
因此,在这个版本的Linux内核源代码中,与系统调用相关的源程序文件包括以下内容:
*拱 / / / i386启动BOOTSECT. S
*玄关 / / / i386内核的设置。
*玄关 / / / i386启动压缩/头的。
*玄关 / / / i386内核的头。
*主/ C。
*玄关 / / / i386内核C陷阱。
*玄关 / / / i386内核的入口。
*玄关 / / / i386内核的IRQ。H
*包括 / / unistd asm-386。H
当然,这只是一个很少涉及的主要文件。事实上,只有包括 / / unistd asm-386。H和拱门/ / /进入i386内核,是通过增加系统修改的文件要求。
(3)修改源代码
(1)增加系统内核中的系统服务例程如下:
asmlinkage int sys_addtotal(int numData)
{ int i = 0,期末余额= 0;
而(我<= numData)
期末余额+ =我+ +;
返回端数据;}
该函数有一个整型参数numData条目从0到numData返回累积值。但是,系统服务例程也可以放在一个文件或其他文件中,但在相应的文件中进行必要的解释是必要的。
该smlinkage int sys_addtotal入口地址(int)添加到sys_call_table表。
最后一行源代码在拱门/ / /进入i386内核的修改之前:
长symbol_name(sys_sendfile)。
。长symbol_name(sys_ni_syscall)streams1 / * * /
。长symbol_name(sys_ni_syscall)streams2 / * * /
。长symbol_name(sys_vfork) / * * / 190
报告nr_syscalls-190。
长symbol_name(sys_ni_syscall)。
模。
修改后,它是:
长symbol_name(sys_sendfile)。
。长symbol_name(sys_ni_syscall)streams1 / * * /
。长symbol_name(sys_ni_syscall)streams2 / * * /
。长symbol_name(sys_vfork) / * * / 190
加上我
长symbol_name(sys_addtotal)。
报告nr_syscalls-191。
长symbol_name(sys_ni_syscall)。
模。
再次,我们需要声明的向量对应的增加sys_call_table表项包括 / / unistd asm-386。H,为了查询或调用的用户进程和系统进程。
的 / usr / / /包括Linux src / / unistd asm-386附加部分。h文件如下:
#定义__nr_sendfile 187
#定义__nr_getpmsg 188
#定义__nr_putpmsg 189
#定义__nr_vfork 190
加上我
#定义__nr_addtotal 191
(4)测试过程(测试C)如下所示:
#包括
#包括
_syscall1(int,int,addtotal,努姆)
主要()
{ int i,j;

printf(请输入一个数);
而(scanf(%d
如果(((J = addtotal(I))= = 1)
printf(系统调用发生在addtotal 的错误()(),n );
printf(总从0到%d %d n
对新修改的内核进行编译,并将其作为一个新的操作系统引导,运行时可以发现所有程序都正常;在新系统下编译的测试程序(注意:因为原始内核不提供系统调用,所以只能在新内核下编译此测试程序)。可以运行如下,编译):
gcc.test美元C测试。
测试
请输入一个数字。
三十六
总数从0到36是666。
修改相关人士进一步分析表明该版本的内核成功后,可以看到在sys_call_table表 / usr / / /弓型Linux i386 / / /进入内核的文件,有几个系统调用服务程序的定义与功能在/ usr / / /内核Linux src / C系统:
asmlinkage int sys_ni_syscall(void)
{返回enosys;}
例如,第一百八十八和第一百八十九是相同的。
长symbol_name(sys_sendfile)。
。长symbol_name(sys_ni_syscall)streams1 / * * /
。长symbol_name(sys_ni_syscall)streams2 / * * /
。长symbol_name(sys_vfork) / * * / 190
两项,在文件 / usr / / /包括Linux src / / unistd asm-386。h,确认如下:
#定义__nr_sendfile 187
#定义__nr_getpmsg 188有些人想流* / / *
#定义__nr_putpmsg 189有些人想流* / / *
#定义__nr_vfork 190
因此,这个版本的内核源代码,这asmlinkage int sys_ni_syscall(void)函数不执行任何操作,所以几个系统包括getpmsg,叫putpmsg,没有操作,就是要扩大空调;但他们仍然占据sys_call_table表,据估计,设计师为了方便的系统调用和安排的扩张,所以你只需要增加相应的服务程序(如增加服务程序getmsg或putpmsg),它可以增加系统调用的函数。
三.结束语
要全面解读Linux内核的复杂性,文章并没有清晰的描述,而与系统调用代码相关的只是内核的一小部分,重要的是掌握好的方法、分析方法,所以分析才是真正分析读者自身需求的向导。
免责声明:本网信息来自于互联网,目的在于传递更多信息,并不代表本网赞同其观点。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,并请自行核实相关内容。本站不承担此类作品侵权行为的直接责任及连带责任。如若本网有任何内容侵犯您的权益,请及时联系我们,本站将会在24小时内处理完毕。
相关文章
返回顶部