`
modabobo
  • 浏览: 502282 次
文章分类
社区版块
存档分类
最新评论

基于Linux0.11源代码的操作系统内核典型处理过程分析1

 
阅读更多

基于Linux0.11源代码的操作系统内核典型处理过程分析1

---进程1执行setup得到硬盘分区表信息

一、背景

操作系统内核的实现复杂性毋庸置疑,其内部各个模块间,软件硬件间的相互协作处理十分复杂,再加上不同进程的切换调度,内核态和用户态之间的相互转换,使得理解其工作原理变得很困难,总有种不识庐山真面目,只缘身在此山中的感觉。

对此,我个人在学习和实践的过程中间走了很多弯路,不敢说现在已经清楚,但至少在如何更好地学习和掌握OS原理和重要的实现细节上有一些方法性的感悟,其中最有效的一点还是确定一条需要理清楚的主干,然后把这条主干上的重要逻辑部分的作用搞清楚,再进一步把每个逻辑部分中的重要实现原理和具体实现方式及关键细节搞清楚,按照这个顺序来一步一步积累,虽然OS的内涵博大精深,但当把想要理解的模块的关键主干抓住了,剩下的基于不同情况下的特殊处理方式和不同OS版本的具体实现上的差别都比较好入手理解和学习了。

因此这里我把自己学习开发OS的过程中发现的一些典型处理逻辑提取出来,整理成资料,实践和总结的过程也让自己受益不少,对很多东西也有种豁然开朗的感觉,希望对大家也能有用。

二、setup获取硬盘分区表信息过程分析

1. setup执行上下文:setup是由进程1执行的过程,实际上是进程10号进程创建出来后要做的第一件事情,虽然setup里包含了获取硬盘分区信息表信息,建立虚拟盘和安装根文件系统设备等很多工作,但这里只分析到获取硬盘分区表信息过程,个人认为这已经是一个可以独立分析和理解的典型过程之一。

进程0 --> 进程1 -->setup <--> sys_setup

( 用户态 )( 内核态 )

可以看出,setup的实际工作是由其对应的系统调用处理函数sys_setup完成的,也即setup入口时是工作在用户态,随后由系统调用进入内核态执行,待OS执行完sys_setup过程处理完相应的请求后返回到用户态,即我们看到的setup()函数返回。关于系统调用的处理流程又是一个典型且重要的过程,我会再另外总结自己的学习心得,这里暂时放一下,并不影响我们要理解的操作过程。

2. sys_setup 获取硬盘分区表信息过程概要分析

sys_setup源代码中关于获得硬盘分区表信息的处理细节很多,我个人觉得最重要的是理清其如何从一块硬盘里得到相应的硬盘分区表信息,至于对硬盘的类型判断和是否存在第二块硬盘涉及的相关处理在本文中不再涉及,这不是要关心的重点。

主要流程如下:

1) 获取硬盘自身参数信息

这一步的作用很明显,如果要读硬盘分区表信息,先要知道即将处理的硬盘自身的基本信息,这样才能对硬盘操作。而这些信息已经在OS最初启动初期setup.s调用BIOS中断得到并保存在物理内存0x90080开始的地方了。

2) 从缓冲区链表中获取一个缓冲区块

这一步的作用是先准备好一块内存,即将来得到的硬盘分区表信息存放的地方。获得这个缓冲区块后,系统会把它标识锁上,这样别的进程就不会有机会操作,相当于临界资源。

3) 准备一条要获取硬盘分区表信息的请求,将其放到硬盘请求等待队列中,进程1睡眠

Linux对设备的操作是封装成请求(request)放到请求队列中统一调度执行的,原因很简单,设备属于有限资源,要使用的人(进程)很多,要求也五花八门,因此统一请求的格式和统一调度管理是很必要的。这里应当注意,request的数目不是无限的,在Linux0.11request最多只有32个,如果请求数已经满了,则当前的进程就得睡眠等待了。

请求发出后,进程1会进入不可中断的睡眠模式,等待所请求的信息完成,除了显示的wake_up重置其状态外,进程调度不会有机会重新执行它。

4) 硬盘设备执行相应的请求获取所要求的信息

这个过程也很复杂,我们忽略硬盘复位和错误检查等细节,总的来说硬盘会读取所要求的数据,每读完一个扇区就发送一次中断,这时相应的中断处理函数就将本次读的数据复制到第(1)步获得的缓冲区中,然后检查是否把所要求的所有扇区都读完了,以调整缓冲区的相应指针准备下一次接收。对于Linux0.11获取硬盘分区表信息来说需要读的是一个块,也就是2个扇区。

如果全部数据接收完毕则置请求等待的进程的状态state为就绪态。

5) sys_setup执行完毕,从内核态返回进程1

由于数据已经获得完毕,进程的状态被置为就绪态(TASK_RUNNING),因此在下一次时钟中断到来时执行进程切换操作就会继续执行进程1,之所以不会切换到别的进程是因为此时系统除了特殊的进程0外就只有进程1。此时就会执行sys_setup从内核态返回的相关操作返回到进程1的用户态了,这样整个过程就执行完毕了。

这里需要指出的是,很多资料和帖子都把将进程的状态state置为0(TASK_RUNNING)称为唤醒该进程,我个人觉得这样很容易造成误解,因为“唤醒”给人的感觉是这个进程已经得到了运行,但实际上它只是被置为就绪态,表明了其可以被调度运行的资格,并没有实际运行,即使在进程调度时也许即将切换的进程也未必就是这个进程,因此个人感觉还是称呼其为置为就绪态更准确一些。

上面大致说明了进程1获取硬盘分区表信息的主要流程,相应关键的具体函数

调用序列如下:

setup(): 系统调用入口。

sys_setup(): 实际的系统调用处理函数,会从内存中取出硬盘参数信息。

bread(): 完成从设备(这里是硬盘)上读去相应信息到缓冲区的操作。

getblk(): 获取一块缓冲区,返回其首地址。

ll_rw_block(): 块设备的读写函数,实际上是逻辑层,由它组织封装设备请求操作,并不参与实际读写操作。

wait_on_buffer(): ll_rw_block最终的结果是发出请求,之后会返回到bread中,此时就需要等待缓冲区被填充,因此要将进程1通过sleep_on置为不可中断的睡眠模式

make_request(): 实际封装请求。

add_request(): 将请求加入设备的请求队列,对于本例它将立即得到执行。

do_hd_request(): 硬盘的实际请求处理函数。

hd_out(): 硬盘的实际操作命令封装函数,将触发真正的硬盘操作。

read_intr(): 硬盘读操作完毕后的中断处理函数,实现了将读取的信息复制到缓冲区

end_request(): 请求结束操作,如果请求处理完毕,则调用wake_up唤醒等待该请求的进程。

3. 一些重要细节

1) 本文讨论的实际上是一个块设备的典型操作流程,涉及到的主要是3方面:设备驱动操作、缓冲区处理、进程调度,虽然主要流程看起来比较简单,但实际的处理细节上主要涉及到的各种分支情况基本上就属于这3个方面,比如请求队列已满、所涉及的缓冲块已存在等等,个人感觉先抓主干,然后再参考这三个方面理细节就稍微容易一些。

2) 关于缓冲区的很多操作都是在关中断方式下执行的,这样做实际上是造成了临界区的效果,目的是防止在临界资源执行过程中被其他的进程或者中断处理误操作,典型的例子就是很多人讨论的wait_on_buffer操作。

3) 关于请求队列,事实上请求队列的使用是包括两部分的:

一是整个请求队列是有限的,申请时是从队列中获取空闲请求资源,且该队列中预留了一定数目的读请求,保证不会全是写请求;

二是封装好实际请求之后,该请求被挂在相应设备的请求链表上,这样每个设备能看见的只是自己要处理的请求链表,并不是整个请求队列,具体可以参考add_request实现,它的第一个参数就是块设备全局变量blk_dev的相应设备结构体地址,这个设备结构体里包含了请求指针,用来索引与该设备相关的请求链表。

分享到:
评论

相关推荐

    linux 0.11 内核源码 - 免费下载

    作为一个基于UNIX的操作系统内核,它的源代码包含了核心代码和一些驱动程序。采用开源开发模式的Linux 0.11内核源代码被广泛研究和修改。在嵌入式设备、服务器和个人计算机等领域,Linux 0.11内核得到了广泛应用。 ...

    Linux内核完全剖析基于0.11内核》--赵炯

    本书对早期的Linux操作系统内核(v0.11)全部源代码文件进行了详细的注释和 说明,旨在让读者能够在短时间内对Linux的工作机理获得全面而深刻的理解,为进一步学习和研究Linux系统打下坚实的基础。书中首先介绍了 ...

    linux0.11内核代码

    完整的 Linux 内核源代码,对linux 内核有一个完整而深刻的理 解,对 linux 操作系统的基本工作原理真正理解和入门。

    LINUX0.11内核源码

    linux0.11 源代码 内有详细分析

    Linux内核0.11版本 学习Linux内核编程极好的源代码

    Linux内核0.11全部源代码,想要深入学习Linux内核编程开发的可以从这个版本的内核开始!

    Linux0.11内核完全注释(附linux0.11内核源码,超全中文注释)

    本书对Linux早期操作系统内核(v0.11)全部代码文件进行了详细全面的注释和说明,旨在使读者能够在尽量短的时间内对Linux的工作机理获得全面而深刻的理解,为进一步学习和研究Linux系统打下坚实的基础.书中首先以Linux...

    Linux0.11源代码及分析资料

    Linux0.11是Linux的第一个正式发行版本,具有里程碑意义,非常值得对操作系统感兴趣的朋友研究,里面是我在网上查找的源码和资料,一起分享。

    linux0.11内核源码

    对于对操作系统和计算机科学感兴趣的人来说,阅读Linux0.11内核源码是了解操作系统内部工作原理的好资源,它可以帮助我们更好地理解计算机系统的工作原理。 虽然阅读Linux0.11内核源码可能需要一定的计算机科学知识...

    Linux内核0.11详细注释+linux-0.11代码.zip

    最精简的linux内核版本,通读有助于对linux操作系统的理解,很好的资料!!!

    linux内核 0.11版本源码 带中文注释

    // 如果定义了__LIBRARY__,则还包括系统调用号和内嵌汇编代码_syscall0()等。 #include &lt;time.h&gt; // 时间类型头文件。其中最主要定义了tm 结构和一些有关时间的函数原形。 /* * we need this inline - forking ...

    linux-0.11源代码

    linux-0.11源代码,本人认为对嵌入式,linux内核研究,操作系统原理与设计都有一定的帮助!

    Linux-0.11内核源码

    Linux 0.11 内核源码包含了操作系统内核的核心代码和一些驱动程序。该内核的开发和维护过程采用开源开发模式,因此它的源代码被广泛地研究和修改。Linux 0.11 内核被广泛地应用于嵌入式设备、服务器和个人计算机等...

    Linux0.11版内核

    本书对 Linux 早期操作系统内核(v0.11)全部代码文件进行了详细全面的注释和说明,旨在使读者能够在尽量短的时间 内对Linux 的工作机理获得全面而深刻的理解,为进一步学习和研究Linux 系统打下坚实的基础。虽然所...

    linux内核0.11完全注释 PDF

    本书对Linux 早期操作系统内核(v0.95)全部代码文件进行了详细全面的注释和说明,旨在使读者能够在尽量短的时间 内对Linux 的工作机理获得全面而深刻的理解,为进一步学习和研究Linux 系统打下坚实的基础。虽然所选择...

    深入分析Linux_内核源代码-pdf版

    《Linux内核完全剖析》对早期Linux操作系统内核(vo.11)全部代码文件进行了详细的剖析,旨在让读者在尽量短的时间内对Linux的工作机理获得全面而深刻的理解,为进一步学习和研究Linux系统打下坚实的基础。...

    linux内核教程

    本书结合操作系统原理以及赵炯博士编写的《Linux 内核完全注释》一书,详细分析了 一个比较适合在教学中使用的操作系统---Linux 0.11 操作系统的源代码。本书从 Linux 0.11 操作系统中引用了丰富的代码实例,并配以...

    Linux内核完全注释(附linux0.11内核源码,超全注释)

    本书对Linux早期操作系统内核(v0.11)全部代码文件进行了详细全面的注释和说明,旨在使读者能够在尽量短的时间内对Linux的工作机理获得全面而深刻的理解,为进一步学习和研究Linux系统打下坚实的基础.书中首先以Linux...

    Linux-0.11 [内核源代码带中文注释]

    目前的内核系统最大长度限制为(8*65536)(512k)字节,即使是在 ! 将来这也应该没有问题的。我想让它保持简单明了。这样512k 的最大内核长度应该 ! 足够了,尤其是这里没有象minix 中一样包含缓冲区高速缓冲。 ! ! ...

    Linux0.11 版内核解析

    Linux内核解析通过对于内核源代码的了解可以加深对于操作系统的了解同时对于嵌入式的内核裁剪也有一定的益处

    Linux 内核0.11 完全注释

    本书对 Linux 早期操作系统内核(v0.11)全部代码文件进行了详细全面的注释和说明,旨在使读者能够在尽量短的时间 内对Linux 的工作机理获得全面而深刻的理解,为进一步学习和研究Linux 系统打下坚实的基础。虽然所...

Global site tag (gtag.js) - Google Analytics