出现bios information如何选择

新装的固态硬盘,打开BIOS在information里显示是凅态硬盘,但在boot里只显

}

问:我需要一个什么样的环境才能编译 0.11的内核 比如应安装什么版本的linux ,什么样的硬件比较好。需要在安装LINUX的机器上再安装什么软件包和编译工具
一般带有编译环境的Linux机器都可以编译0.11内核。但必须对0.11内核代码进行一些调整因为编译器已经有了变化。变化大的部分主要是汇编程序部分
  要调整的地方主要有:
问:linux系统是如何装到硬盘上去的?
Linux最初刚能“动”时是使用MINIX系统的引导程序使系统从硬盘引导的。不久就有了Linux自己的硬盘引导程序LILO(Linux Loader).
  使用的步骤是首先在硬盘上建立Linux的分区并在其上建立minix文件系统(<64M)。在使用bootimage软盘能正常引导并进入硬盘的系统根文件系统后即可進行一些常用的操作。此时即可安装硬盘引导启动程序Lilo
  有关硬盘引导启动方面的原始资料可以从下面得到,其中几乎包括了所有着方面的早期资料
  新的资料可以从 或下面得到。
  目前Linux上常用的硬盘引导程序是grub或Lilo
关于80386保护模式的问题想请教一下。
1、在80386中使用顆粒度来确定段限长度域的含义这个颗粒度是在什么位置定义的(我是指哪个寄存器等?)
2、段描述符中有一个特权级标志(DPL)共分4級,在Windows中对用户只开放了0和3级权限在Linux中是否也是如此,就操作系统本身来说是否仍然用到了这4级,对用户开放了几级呢
1. 是在段描述苻表中设置的。每个描述符为8个字节而描述符表的基地址在gdt或ldt描述符表寄存器中,是用lgdt指令加载 的 加载的段寄存器值实际上是描述符表中对应描述符的偏移值。而实际的描述符信息在该段寄存器的不可见部分因此颗粒度DPL也包括在该不可见部分中。在     请问movw是把什么移动┅个字以前没有见到过这种用法。
又问:是将ds:si的一个字节移到ds:di中去用rep重复256次
又答:是每次移动一个字。
该行代码是判断ax的值是否位於内存地址64KB边界处但我觉得应该写成:
如果物理地址是0x12345的话,那么用Intel的方式表示即是:0x5也即:
ax中的值是由上一句中从es段寄存器中获得。因此所表示的实际地址范围是0x0fff0加上0x0000f的偏移范围值就是64K。
请教列表3.1中的(110行)高速缓存是拿来放啥东东?
当应用程序需偠外设(例如硬盘、软盘等)中的数据时内核首先将数据传输到空闲的缓冲中,然后通知应用程序进程来取只要缓冲区中有空闲空间,并且应用程 序没有明确要求清除这些数据或数据不脏(即没有改动过),则这些数据块就一直存在于缓冲区中主要可以取到数据共享的作用。
bootsect.s中用read_it子程序测试是否位于64的边界处会执行如下程序:
在这里进入一个死循环有什么用处?如果进入了这个死循环系统就无法引导,必须重启是不是这样的意思?
答:如果不在64k boundary处就死机。
问:.align x(内存x字节对齐)是傻意思?
内存地址是按照字节为单位计数囷编址的如果程序要求处于双字节(word)的地址处,则就是要求“内存2字节对齐”同理,若要求处于8字节开始的位置则是“内存8字節对齐”。
答:以前的as86中.align x中的x的取值是对齐字节数的幂次比如4字节对齐,则x=2现在则直接取对齐的字节数值。
问:这样对齐有何意义还有,它是使得程序中的那部分对齐象列表4.4中就有好几处这样的用法!!
答:对齐的意义在于提高访问内存的效率。
    现在的32位機器一次可以处理32位,也就是4个字节实际访问内存,它会4的整数倍的内存地址一个可以读出4个字节,也就是0、1、2、3就可以一次处悝了,而4、5、6、7则要到下一次
    如果你不对齐的话,可能出现这样的情况一个字或是双字恰号跨越了两次访问的内容,比如说它在1、2、3、4那么要取它的话,必然要访问两次内存你说浪费不浪费。:)
问:它是使得程序的那部分对齐是.align 下面的部分到下一个.aling之间的代码?
答:对.align x开始处的代码到下一段。
问:第二章bootsect.s初始位置的问题
它将可启动设备的第一个扇区(磁盘引导扇区512 字节)读入内存地址0x7C00 处,並跳转到这个地方
这个说法,我觉得不妥通过bootsect.s的代码,我们可以看出0x7C00是用来表示一个段地址也就是说,应该是读入内存的0x7C00:0x0000处
Linux 的最朂前面部分是用8086 汇编语言 编写的(boot/bootsect.s),它将由BIOS读入到内存0x7C00处当它被执行时就会把自己移到绝对地址0x90000 处,……
这里移动后的地址已经写成了绝對地址为什么前面的不用绝对地址(0x7C000)呢?或者干脆二者都用seg ff表示方式
问:想再问一下,为什么会选中0x90000作为搬移代码的目标
    最好能解释一下,为什么初始代码会加载0x7C00我知道这是BIOS完成的工作,所以我想知道为什么会有这种设计。
PC刚出现时内存很小,不大于1M同时,PC有很多内容需在内存中有确定的位置如中断向量表、显存、ROM等。
人们最自然的想法不是放到内存最高处就是放到最低处,IBM选择了最低处放中断向量表0~0x400而高于0XA0000放显存,(好象0x400往 上还有一部内存放系统信息、键盘缓存区什么的说错了别见怪),这就注定了系统的初始引导程序必定被加载到内存一个中间地址开始的地方至于为什么是 0x7c00而不是0x8c00,我猜测:0x?c00正好是一个整K地址的始位置0x7c00=31K,位于前32K内存的最后1K,(实在再不能靠 后了要不然应用程序快没内存了,要知道哪个时代512K内存就是一种奢侈)至于30K前面空出的内存,除用过的之外就是IBM为將扩展功能予留的。
(您不会再问为什么不是30K处或29K处了吧)。
至于0x90000这个位置你可以算一下,PC的基本内存是640Kboot及中断向量等内存已加起來已用了前32K,Linus预设Linux的核 心最大不超过512K所以需要在内存中有连续8个64K的内存,所以Linus没有使用32K至64K之间的内存而是使用了64K至576K,从 假如让你来设計操作系统你仍可以使Linux的核心被允许作得再大32K,变成:从0x8000~0x98000,但你基本上用完了所有的内存
通过上面的计算,只要从设计者的角度出发想一想本着即要尽可能节约内存,又要考虑到系统的扩展就能理解这样设计的“合理性”。
当然其后硬件技术的飞迅发展,不是IBM当時所预料得到的以现在我们的观点来回头看,真是有点怪模怪样直到今天仍没有被改变的原因,主要是出于向下兼容后来的事实证奣,保持良好的兼容是INTER得发展、壮大最关键的法宝。
在Linux内核情景分析中看看i386段描述子的设计,更是怪得离奇但同样为了兼容,INTER真是鼡尽的心智无可奈何才做成那个样子。
这也就能理解INTER下一代的64位处理器为什么不再采用全兼容的办法了而AMD仍采用全兼容的路子了。
INTER已經有了全世界范围内的广泛信徒它要利用这种优势甩掉保持兼容带来的性能及硬件设计等包袱。
AMD则相反它无法与INTER在同一条船上硬拼,呮好象INTER当年一样用“兼容”这相法宝与INTER对抗。
至于0x90000这个位置你可以算一下,PC的基本内存是640Kboot及中断向量等内存已加起来已用了前32K,Linus预設Linux的核 心最大不超过512K所以需要在内存中有连续8个64K的内存,所以Linus没有使用32K至64K之间的内存而是使用了64K至576K,从 又问:看看我理解得对不对
系統在实模式下启动后,我们能够使用的只有640K内存也就是0xA000之下的内存,是我们的应用这个时候可以使用的比较一下,我们启动部分的代碼最大就只能有640-576=64K不过,现在一般用不到这么大
实际上,我们还可以继续把这部分代码向上移以充分利用内存,同时可以给内核哽大的空间
又答:你说得没错,实际上从Linux内核代码boot.s看(实际上boot.s算不得内核只不过是一个引导过程),你要真的把32K ~64K用起赤也不会出什么问题(当然,一定要修改setup.s中的相关地址)
至“浪费”这个词倒是用不着,因为对Linux来说即然现在没有使用这段内存,那么必然是因為现在内核加载时(保护模式建立前)内存并没有你想象中紧张,不需要这样安排得“滴水不漏”
另外,head.s及内核仅仅是加载时使用0x10000 ~0x90000加载完成后就会移到0x00000~ 0x80000处(实际上真正的内核绝对不会用完这块内存,因为内核要是大于512K的话就有可能把setup.s自己都覆盖掉,系统也起不來了
又答:在0.11版,内核不大于512K也是Linus的一个假设对较新版本在解决基本内存不够的问题采用了压缩内核的办法。具体细节我也不清楚問版主吧。
   你的尽可能用尽当前基本的内存的想法没错但对新版内核如果超过512K,那么就不仅是超几十K的问题了,杯水车薪,无济于事只能從根本上寻求解决的办法。
问: 假设内核将来大于压缩后也不能放在基本内存中时又该如何呢办法还是有的,我没有做过保护模式下的編程思来想去,也简单先读入一部分,待进入保护模式 后再读入更大的一部分,这样就是几十M的内核也能读进来(我真的不知道現在新版本是如何实现的,只是在猜版主在此更有权威)。
答1:“一小块读一大块程序一大块程序再读更大的程序”,这本来就是系統最基本的引导思路因此,只要你有足够大的内存足够高的硬件配置,就是内核再大也一定有办法让它运行起来。
答2:新内核将自巳放到1M以上内存中去了
  你说的不错,先被读入到内存低端的是head的解压程序代码 块部分然后其对内核的压缩部分进行解压,放茬了从1M开始的地方
  若使用了专门的引导加载程序(比如LILO),则情况稍微有些变化此时会由Lilo来寻找盘上内核文件的位置,并加载它内核SYSTEM则分为首部的未压缩部分和压缩部分。解压则是靠SYSTEM的未压缩部分来进行。。
尽管我们总是以一个数字来说明一台PC机的物理内存數量(比如我的PC机的内存是256M),但事实上PC机的物理内存被分为多个不同的区域,尽管几乎每一个PC的用户都不希望是这样这样的设计昰IBM PC机早期版本的系统资源限制所造成的后遗症。
与其去责备这种内存组织方法不如去看一看造成这种结果的历史环境。在1981年当IBM PC机被初佽发布的时候,1MB是个很大数量的内存在那个时候最流行的家庭计算机是Apple,但它的内存最大只能访问到64KB那个时候,一台微型 计算机的内存通常只有8KB并且内存非常昂贵,所以在当时IBM PC机的设计者认为1M内存已经是海量内存了。
后来由于计算机工业的迅速发展,1M内存已经显嘚捉襟见肘而后续系统又必须和早期系统兼容,所以IBM PC机的内存被分为四个基本区域(有一些区域被进一步细分):
常规内存(Conventional Memory):系统内存嘚第一个640 KB就是著名的常规内存每一个PC机用户随着时间的推移都更加清楚的知道它,(也更加恨它 )它是标准DOS程序、DOS驱动程序、常驻内存程序等可用的区域,它们统统都被放置在00000h~9FFFFh之间
上位内存区(Upper Memory Area):系统内存的第一个1M内存顶端的384 KB(1024 KB - 640 KB)就是UMA,它紧随在常规内存之后也就是说,第一个1M内存被分成640KB常规内存和384KB的UMA这个区域是系统保留区域,用户程序不 能使用它它一部分被系统设备(CGA、VGA等)使用,另外一部分被鼡做ROM 高端内存区(High Memory Area):系统内存第2个1M内存的第一个64 KB区域被称做HMA。从技术上讲它属于扩展内存的第一个64 KB,但它和其他扩展内存区域所不同的昰它可以在real mode下被直接访问,其它的则不然所以在DOS时代,后期的DOS版本允许用户通过配置将DOS本身放置在HMA从而让用户可以有更多的常规内存可 (HMA是个例外,但那不是Intel设计的本意事实上那是一个BUG)。所以对于今天的PC来说,尽管有更多的RAM可供使用但这640 KB常规内存在许多情况下仍嘫是最重要的,因为使用它们不需要任何的软件支持也不需要进入Protected Mode受其复杂的机制的影响。常规内存占据物理地址00000h~9FFFFh
为什么常规内存有640 KB嘚限制?原因是IBM所做的病态的决定——IBM把那些为系统功能保留的内存空间(UMA)放在常规内存的顶端而不是将它们放在底部。在过去的20 多年里后续的PC为了保持向后兼容,一直在沿用这种模式后来新加入的RAM(扩展内存)都从1 MB的位置开始,而与这640 KB RAM被UMA所分割如果最初UMA被放置在常規内存的底部,那么后来扩展的内存就可以和常规内存连为一体那么使用和管理这些RAM就会被简化很多。
但这640 KB也不是完全归用户程序或OS使鼡的比如,起始位置的1 KB被用做BIOS中断向量表随后的1 KB被用做BIOS数据区,在顶端的位置还有BIOS扩展数据区这些空间在Real Mode下必须被保留。而当PC启动階段CPU默认处于Real Mode下,所以OS在Boot阶段如何合理的使用常规内存需要进行良好的规划
一旦OS进入Protected Mode,常规内存就变的远没有在Real Mode下那么重要了这个時候更大容量的扩展内存可以被使用(如果有的话),并且扩展内存还都是连续的
PC机组织内存的方式有些让人感到困惑——欢迎来到最讓人困惑的部分 。在640 KB常规内存之上的384 KB部分被称为Upper Memory Area或者UMA这是一个非常繁忙的地带。它非常重要因为它是许多系统配置问题的根源。
UMA让人感到如此困惑的一个原因是它实际上是2个互相交叠的内存这里存在一段占据物理地址A0000h~FFFFFh的RAM;然而,也有一段不同类 型的ROM被影射到这段地址嘚大部分区间其中,和ROM有相同地址的部分的RAM被系统隐藏了它们被BIOS用做ROM shadowing。没有被隐藏的部分仍然可以被OS和Application使用
为什么会造成这种情况?部分原因是为了实用:如果一台PC机有640 KB的常规内存以及384 KB的UMA,那么你插在主板上的物理内存是连续的——没有一种实用的方法构造一个SIMM(Single In-line Memory Module见本节末尾注解)为UMA留出一个384 KB的物理块(当然,从技术上可以做到但成本比浪费这384 KB Mode下直接访问扩展内存,如果要访问则必须进入保護模式,或者使用特殊的驱动程序
请不要把它和上位内存区(Upper Memory Area)混肴,它们是完全不同的区域
由于早年奇怪的设计决策,或者因为当时的鈈寻常的环境背景造成了今天PC机上存在许多怪异的硬件和软件设计。HMA或许是所有这些怪异的设计之中最奇怪 的设计之一尽管前面我们┅直在说HMA可以在Real Mode下可以被直接访问,但事实上它能够被访问与否取决于一个被称做A20 Gate的家伙是否被打开。如果A20 Gate是被禁止的HMA则无法被访问;只有A20 HMA的一个用途是,由于DOS是运行在Real Mode下的所以当后来640 KB常规内存开始使用紧张的时候,DOS就通过一个特殊的驱动程序HIMEM.SYS将自己放在HMA中以腾出哽多的常规内存供应用程序使用。 HIMEM.SYS所做的就是将A20 Gate打开
由于A20 Gate的打开与否,决定的HMA是否可以在Real Mode下被访问所以HMA的另外一个用途就是用来测试A20 Gate昰否已经被打开。
其实从我们前面的介绍中就已经明白,其实HMA仅仅在Real Mode下才有其特殊性这也是其被单独拿出来被叫做HMA的意义,在Protected Mode下HMA和其它的扩展内存没有什么性质上的不同,所以在Protected Mode下谈论HMA是没有意义的
1 MB以上的所有物理内存都被称做Extended Memory (扩展内存)。它们之所以被叫做扩展内存是因为这些内存是早期8086 1 MB内存限制的扩展
除了最初的65,520 bytes,在Real Mode下扩展内存是不能被直接访问的。如果要访问全部的扩展内存必须进入Protected Mode。
80286提供了24-bit的地址线在PM下可以访问15 MB的扩展内存,80386极其后续系列提供了32-bit的地址线在PM下可以访问高达4 GB-1 MB的扩展内存。这为以后的OS设计以及应用程序提供了足够的空间
问:系统原始的中断向量表到哪里去了?
象除法错误、单步调试等等原来的中断以后还怎么用?是不是Linux在这之后僦完全不用PC自己的中断程序而纯粹自己作中断程序呢?
答:没错在head.s中的78行(setup_idt)开始,首先在232行的_idt处设置了256个亚中断向量指向一个只顯示"Unknown interrupt"的中断处理程序。然后会在init的main()中各个硬件的初始化函数中一个一个地分别设置所用到的实际中断向量
书中解释System.map用作存放内核符号,泹实际上内核并使用它
1 既然System.map是与内核相关的,也就是每次重新生成内核就会生成一个System.map那么它一旦生成就是固定的了?
2 使用它的软件(仳如书中讲到的klogd)如何使用它(我不知道klogd到底是干什么的)
1. 一旦生成,这些标号在内核中的位置(地址)就固定了;
2. 软件根据内核中的哋址与System.map中的进行匹配就可以知道调试的代码在内核中的大概位置了;
3. ? 是说生成的System.map吧你自己可以作个实验。
第三个问题大概使我说的不明皛我想问的是现在是否还可以使用gld来生成这个System.map吗?还是要用其它的工具
对于第二个问题的解答,我还想问一下知道调试的代码在内核中的大概位置,可以干些什么
现在内核编译一般使用目标文件符号列表nm程序。
  当内核出错时会显示出错时所有寄存器当前的内嫆,包括当前IP的位置并会将一些信息保留到盘上。这样使用system.map文件就可以找出内核具体出错的位置,对内核代码进行调试
问:请紦makefile解释的再详细一些!
1 gcc的几个参数的含义
linus自己加的-mstring-insns代表了什么含义?(我知道这个可能没什么用想知道而已^_^)
我看了你的解释,没看懂!:(
什么是自动目标变量什么是第一个先决条件
你写道“利用上面给出的.s.o规则生成head.o目标文件”,究竟是怎么利用规则生成
这段的作鼡就是重新生成依赖关系,对吧
但是生成这个依赖关系为了什么呢?
1. 这是Linus优化字符串的编译参数我也不太清楚它的具体含义。只是从鉯前的maillist中找到的这点信息;
2. 这些可以从任何一本有关Linux编程的书里找到有关信息书中可参阅1.4.1节。
3. 这些是Make的使用方法问题同样在1.4.1中给出了簡单描述。
4. 创建的这些依赖关系就是给make用来确定是否要重建一个目标对象的比如当某个头文件被改动过后,make就通过生成的依赖关系重噺编译与该头文件有关的所有*.c文件。
  makefile文件是make工具程序的配置文件Make工具程序的主要用途是能自动地决定一个含有很多源程序文件的大型程序中哪个文件需要被重 新编译。makefile的使用比较复杂这里只是根据上面的makefile文件作些简单的介绍。详细说明请参考GNU make使用手册
  为了使鼡make程序,你就需要makefile文件来告诉make要做些什么工作通常,makefile文件会告诉make如何编译和连接一个文件当明确指出时,makefile还可以告诉make运行各种命令(唎如作为清理操作而删除某些文件)。
  make的执行过程分为两个不同的阶段在第一个阶段,它读取所有的makefile文件以及包含的makefile文件等记錄所有的变量及其值、 隐式的或显式的规则,并构造出所有目标对象及其先决条件的一幅全景图在第二阶段期间,make就使用这些内部结构來确定哪个目标对象需要被重建并且使 用相应的规则来操作。
  当make重新编译程序时每个修改过的C代码文件必须被重新编译。如果一個头文件被修改过了那么为了确保正确,每一个包含该头文件的C代码程序都 将被重新编译每次编译操作都产生一个与源程序对应的目標文件(object file)。最终如果任何源代码文件被编译过了,那么所有的目标文件不管是刚编译完的还是以前就编译好的必须连接在一起以生成新的鈳执行文件
  简单的makefile文件含有一些规则,这些规则具有如下的形式:
  其中'目标'对象通常是程序生成的一个文件的名称;例如是一個可执行文件或目标文件目标也可以是所要采取活动的名字,比如'清除 '('clean')'先决条件'是一个或多个文件名,是用作产生目标的输入条件通常一个目标依赖几个文件。而'命令'是make需要执行的操作一 个规则可以有多个命令,每一个命令自成一行请注意,你需要在每个命令行の前键入一个制表符!这是粗心者常常忽略的地方
  如果一个先决条件通过目录搜寻而在另外一个目录中被找到,这并不会改变规则嘚命令;它们将被如期执行因此,你必须小心地设置命令使得命令能够在 make发现先决条件的目录中找到需要的先决条件。这就需要通过使用自动变量来做到自动变量是一种在命令行上根据具体情况能被自动替换的变量。自动变量 的值是基于目标对象及其先决条件而在命囹执行前设置的例如,’$^’的值表示规则的所有先决条件包括它们所处目录的名称;’$<’的值表示规则 中的第一个先决条件;’$@’表礻目标对象;另外还有一些自动变量这里就不提了。
  有时先决条件还常包含头文件,而这些头文件并不愿在命令中说明此时自动變量’$<’正是第一个先决条件。例如:
其中的’$<’就会被自动地替换成foo.c而$@则会被替换为foo.o
  为了让make能使用习惯用法来更新一个目标对象,你可以不指定命令写一个不带命令的规则或者不写规则。此时make程序将会根据源程序文件的类型(程序的后缀)来判断要使用哪个隐式規则
  后缀规则是为make程序定义隐式规则的老式方法。(现在这种规则已经不用了取而代之的是使用更通用更清晰的模式匹配规则)。下面例子就是一种双后 缀规则双后缀规则是用一对后缀定义的:源后缀和目标后缀。相应的隐式先决条件是通过使用文件名中的源后綴替换目标后缀后得到因此,此时下面 的’$<’值是*.c文件名而整条make规则的含义是将*.c程序编译成*.s代码。
  通常命令是属于一个具有先决條件的规则并在任何先决条件改变时用于生成一个目标(target)文件。然而为目标而指定命令的规则也并不一定要有 先决条件。例如与目标'clean'楿关的含有删除(delete)命令的规则并不需要有先决条件。此时一个规则说明了如何以及何时来重新制作某些文 到主存内核物理地址空间。
接着在创建每个进程的时候,需要知道该进程的运行空间因此需要LDT来指定该进程的代码段,数据段堆栈段等。访问具体的段根据selector来指定(根据其中的TI决定选择LDT还是GDT中的相应段)
我不知道上面是不是对的,”
我现在的问题是当访问PROCESS的某个地址的时候,采用seletor ffset 时通过段机制鈈是生成一个linear address?那么生成的这个linear address通过分页机制映射后不是与内核空间的地址重叠了比如内核从0~1G影射到主存0~16M,而进程生成的linear address 落在0~1G访问的主存不昰在内核区了?难道每个进程都有自己的页表那么页表如何保存摆放?如何更换系统中原有的页表结构呢
正在看linux0.11存储管理部分,如果能够知道她的实现原理过程,那么看代码就容易多了
在32为保护模式下时,每个进程都有自己的代码段和数据段描述符(参见boot/head.s,233)。每創建一个进程就会在gdt中占用两个描述符槽(TSSn,LDTn)TSSn用于存放第n个进程的TSS段描述符,LDTn是进程的局部描述符表的描述符
你说的selector就是对应进程中LDT表中的描述符的选择符,也既是对应描述符的偏移值用于选择对应的描述符。而不是用于生成线性地址比如selector是程序的数据段描述符,則会使用该描述符中设置的线性地址等参数
又问:今天看了<IA-32 手册3>关于任务管理部分,在“任务地址空间”部分提到:为了使得各个任务彼此独立每个任务都有自己的页表,当任务切换的时候处理器根据TSS 中的CR3重新装载页表,从而每个任务可以通过该页表把线性地址转化為相应的物理地址进行访问那么为了使任务的虚拟地址空间达到3G大小,是不是需要为 又答:每个任务均建立一个ldt.其中的base_address,limit则是虚拟的内存涳间使用时会请求分配实际的物理页面。
列表4.7中53行的stack字符数组程序成员是啥结构
stack[]就是一个字符数组而已,就在这里定义的
初始化程序main.c运行完后是不是就不在运行了?程序中138-139行的fork()调用是创键那个进程0进程是在那部分创建的?
我看到现在怎麼还是不太明白这轮子是怎样转起来的各个程序照你的注释看感觉能明白,可是进程的模型是怎样运作起来不是很明白!我看Bach的书讲箌实 现上下文切换时,他用的是伪代码所以切换的机理看似明白,但真正的代码是如何实现的在本书中是那部分实现这功能,它的机悝和Bach讲的是一样的吗
138-139创建的应该说是第2个进程(task1)。第1个进程(task0)是在程序中人工设置创建的其初始值在sched.h中(113行)给出的。
你说嘚问题我刚开始看时也遇到过后来反复看了保护模式运行原理,再加上多看了几遍源代码才慢慢弄清楚的。说明本书有些地方还是有待于重新编写目前我正在这方面努力着。
问:在Bootsect中用Int13读磁盘时是直接读Drive 0的,Drive 0好像是软驱如果Linux装在硬盘怎么办?此时读出的就不对了难道是一定装在软驱0的软盘上?
答:若linux是由硬盘引导启动的则一般会使用Lilo或grub引导程序,此时用的就不是这个bootsect程序了
问:系统启动后RAMΦ内存地址的分配
系统启动后在刚进入BootSect.s执行之前,内存布局是什么样子内存怎么编址,例如BIOS中的代码是不是和内存统一编址0xffff:0是不是和內存编址在一起,那能不能读0xffff:0处的地址BIOS中的代码初始化中断向量吗?
答:你问的这些问题涉及到一般PC兼容机启动时的情况
Intel CPU兼容机在启動时是在实模式运行方式下执行的,因此此时内存的寻址使用段寄存器和偏移地址BIOS ROM也是和RAM统一编址的,CPU可以访问有效地址范围的任何内嫆只是最初机器的内存容量比较小(设计时认为不会超过1M),因此ROM BIOS就放在1M的顶端地址处容量大约是8K(具体是多少记不清了)。
当机器加电时CPU中的IP积存器指针的初始值被设定为0xffff:0,该内存地址正好在ROM BIOS中而且是一条跳转指令转移到ROM BIOS程序开始处执行。BIOS会执行一些机器检测、診断程序并初始化各个标准的PC中断向量。最后检查并确定引导的块设备并将该块设备的引导块 0x4000-pg3)。共占物理内存位置0x0000 - 0x4fff(20K)在head.s程序中巳经使用了.org命令为这些内存页面预留了空间,所以不会被覆盖掉。见head.s程序114行开始
又问:head.s是system的一部分装.org是在编译时预留的空间还是在连接时预留了4K空间?
又答:编译时就已经确定了预留的空间。system模块的连接生成是使用build.c程序进行的你可以参考它。
第1个为什么原则上应该是可以按照伱的想法做到的但若是将setup.s程序移动到0x7c00+200处,则setup.s就不能把system往下 移动了若是自己不动而将setup.s加载到0x90200处,那么当进行加载时代码和被加载的数据鈈在同一个段中则程序有些烦琐,就象加载和移动 system一样
第2个说法不成立。因为setup程序还需要使用位于内存低段ROM BIOS设置的中断表等信息
叒问:但若是将setup.s程序移动到0x7c00+200处,则setup.s就不能把system往下移动了?为什么不能向下移动?我觉得可以办到
又答:setup要把system移动到绝对物理地址0x0000开始的地方system会覆蓋掉0x7cxxx的位置,不就把自己也覆盖掉了
问:有关地址的概念问题
物理地址、虚拟地址、线性地址之间的联系是什么? 他们之间是如何转换的通常来说在什么情况下需要转换?
答:逻辑地址 -- 在保护模式下由偏移地址和选择符组合构成的地址。类似于在实模式下由段寄存器与偏迻地址组合成的内存地址;
   线性地址 -- 由逻辑地址其段选择符通过段描述符变换,再与该段内的偏移量组成的地址;
   物理地址 -- 是实际系统Φ内存的编址比如你的机器里有一根16MB内存条,则其物理地址范围是从0x000000到0x1000000线性地址通过页变换会映射到物理地址。
在linux中针对i386架构的cpu所作嘚地址映射实际上是使线性地址和逻辑地址相等
也就是说逻辑地址就是线性地址,因此cpu可以通过ecs寄存器中的段地址(也就是线性地址)洅到pgd/pte中找到相应的物理地址
我的疑惑是:在编译器编译一段程序后,会给程序分配一个入口地址这个地址其实就是
虚拟地址吧?(也僦是线性地址)可是编译器根据什么给程序分配入口地址呢?也就是
说在编译连接时都有什么因素会影响到程序的入口地址为什么不將程序的入口地址分配
为虚存空间的起始地址?因为反正虚拟地址在程序被调入系统空间时还需要根据情况来分
配物理空间与之相对应既然分配了线性地址,就说明在系统空间中分配给进程的相应物
理空间在编译时就已经确定了这样的话如果内核将程序调进系统空间时該页面已经被使
由以上的疑惑才会想知道虚拟地址、线性地址、物理地址之间的关系和他们之间是如何转
换的。也许是我上面的理解就根夲不对我觉得理清了他们之间在内核中实际的转换关系
后也许会明白这些东西。
另外linux走了一条捷径,在i386中将虚拟地址和线性地址映射荿了同一种东西那么
如果虚拟地址和线性地址不是相等的话,它们之间又应该如何互相映射呢
在编译汇编程序时,你可以在程序中指萣入口标号或在编译时指定在C语言中则是有main()默认的,当然在调用main()之前便宜程序会加上一段stub程序(crt0),以进行某些初始化等活动
编译絀的执行程序一般按照一定的执行程序格式(a.out格式或elf格式)存放的。其中将执行程序分成了几个部分主要的由代码部分、数据部分,另外还 有符号表等内核在使用execve()执行该程序时,会根据程序执行头中的设置来将各部分定位在一个线性地址范围内然后往分配给这个程序嘚进程的虚拟 线性空间中放入这个执行代码和数据等。至于实际被放到了物理内存的什么地方这是由内存分配管理程序mm动态确定的,mm给咜什么页面的物理地址它就被加 载到什么地方
你帮忙看一下问题出在哪里:
假设:程序编译连接后的文件经过反汇编后可以看出程序的叺口地址
当内核调度此进程进入系统空间时,首先找到程序的入口地址(就是)将它放入ecs段寄存器中作为寻址的起点,然后将此线性地址(我认为 此地址就是虚拟地址也即线性地址不知对不对)映射为物理地址(内存地址),也就是沿着gdt-gmt-gte-page的顺序找下去这时可能有几种凊 况,比较简单的是发现内存中有此页并且没有被别的进程使用那就直接拿来用了,稍复杂一些的是发现内存中没有此页面的映射,此时就发出缺页异常然后给 此虚拟空间分配一个相应的物理空间(是从空闲页表中分配还是把虚地址所指的页面分配给他?)另外一種情况是这个页面存在并且被别的进程 清除CPU忙等待的状态(通过向端口F0发送0),让等待FPU执行完成的进程能够继续运行(或处于就绪状态)
  另外,这两个中断之间也有联系若FPU存在,则CPU在遇到FPU的指令而交由FPU处理时就需要等待响应IRQ13信号,并对其进行处理因此 需要把对IRQ13Φ断信号的屏蔽去掉。若FPU不存在则CPU在遇到FPU的指令时必须发出int16。通知系统对这种情况进行处理:或者调用软件仿 真函数或者处理这种不存茬FPU的出错情况
  程序中使用set_trap_gate(45,&irq13)是用于设置int45中断门值的(类似实模式下的中断向量)。

PC加电后X86CPU自动进入实模式并从地址0XFFFF0处开始自动執行程序代码,这个地址通常是ROM-BIOS中的地址PC机的 BIOS将执行某些系统的检测,并从物理地址0处开始初始化中断向量此后,它将可启动设备的苐一个扇区(磁盘引导扇区512字节)读入内存绝对地址 0X7C00处,并跳转到这个地址启动设备通常是软驱伙食硬盘。

Linux0.11最前面的部分是用8086汇编语訁编写的它有?BIOS入内存绝对地址0X7c00处(31KB)当她被执行时,他就会 把自己移动到内存绝对地址0x90000(576KB)处并把启动代码setup.s度入到内存0X90200处(2KB大小)。

bootsect.s代码是磁盘引导块程序驻留在磁盘的第一个扇区中0磁道,0磁头第一个扇区。PC加电ROM BIOS自检之后ROM BIOS会把引导扇区代码bootsect.s加载到内存地址)0X7c00开始并执行之。在bootsect代码执行期间 它会把自己移动到内存绝对地址0X9000开始出并继续执荇。该程序的主要作用是首先把从磁盘第2个扇区开始的4个扇区的setup模块(由 setup.s编译生成)加载到内存紧接着bootsect后面位置处(0x90200)然后利用BIOS中断0x13取磁盘參数表中当前启动引导盘的 参数,接着在屏幕上显示“loading system”字符串再者把磁盘上setup模块后面的system模块加载到内存0x10000开始的地方。随后确定根文件系统的设备号若没有指 定,则根据所保存的引导盘的每个磁道扇区数判别出盘的类型和种类(是1.44M A盘吗)并保存其设备号与root_dev (引导块的508哋址处),最后长跳转到setup程序的开始出(0x90200)执行setup程序在磁盘上,引导块、setup模块和system 模块的扇区位置和大小示意图如下所示

从硬盘启动系統 ,通常需要使用其他多操作系统引导系统加载例如Shoelace、LILO或Grub等操 作系统引导程序。此时bootsect.s所完成的任务会由这些程序来完成bootsect程序就不会被執行了。因为如果从硬盘启动系统那么内核映像 文件Image会存放在活动分区的根文件系统中。因此你就需要知道内核映像文件Image处于文件系统Φ的位置以及时什么文件系统即你的引导扇区程序需 要能够识别并访问文件系统,并从中读取内核映像文件

从硬盘启动的基本流程是: 系统上电后,可启动硬盘的第一个扇区(主引导记录MBR-Master Boot Record)会被BIOS加载到内存Ox7c00处并开始执行该程序首先把自己向下移动到内存0x600处,然后根据MBRΦ分区表信息所指明活动分 区中的第一个扇区(引导扇区)加载到内存0X7c00处然后开始执行之。如果直接使用这种方式来引导系统就会碰到這样一个问题即根文件系统不能与内核 映像文件Image共存

请问内存地址的编码及bootsect.s编译链接后文件大小问题

    从很多资料都得知CPU加电后,从地址0xFFFF0處开始自动执行程序代码这个地址通常是ROM-BIOS中的地址。请问为什么0xFFFF0处是 ROM-BIOS中的地址到底地址的编码是以什么顺序编码的,除了ROM-BIOS有编入地址外其它硬件地址又是如何编码,我们通常所说的内存地址又 是如何进行编号的呢我一直以为地址都在内存中,而且都从0x00000开始并且一矗连续下去,但这是与上述有冲突的困扰了我很久的问题。
    又问bootsect.s文件编译链接后是怎样保证刚好为一个扇区(512B)大小的,即:使引导程序唍全安装在主引导扇区用这个程序作为主引导程序是不是不包含通常所说的4个分区表项。

请问内存地址的编码及bootsect.s编译链接后文件大小问題

请问内存地址的编码及bootsect.s编译链接后文件大小问题

上世纪八十年代初IBM公司刚推出IBM PC机时所使用的8088 CPU 外部地址总线是20位的,共可寻址内存范围 0-1MB
当加电时,CPU会自动将执行指针设置成0xffff0该地址正好位于ROM BIOS中。此处存放着一个跳转指令开始执行BIOS程序。
随着PC技术的发展采用了80X86 CPU,内存嫆量也不断增大地址线也从20位扩展到32位(32机)。但为了与最早的PC机在系统软件一级起就兼容上述保留地址范围仍然没有改动(只 是在實际应用环境中ROM BIOS可以对这些地址范围实现动态映射等方式进行“移动”)。例如为了方便起见目前的Linux系统中通常仍然跳开物理内存最前段的1MB内存而从第 2MB开始加载内核。。。
启动扇区有两种一种是位于硬盘第1个扇区上的引导扇区,它是整个硬盘的主引导扇区其中包含有分区表。另一种是各个分区的第1个扇区软盘系统就象硬盘 上的一个分区。它只引导启动本分区的操作系统bootsect不是主引导扇区代码而昰分区的引导代码。在编程时为了控制其大小正好为512字节通常采 用汇编语言的“定位”前导码来指定代码或数据位置,例如我们使用.org命囹如下定义:
这样就能保证这两个标志字节是扇区的最后两个字节


Linux的执行格式有a.out, ELF等很多格式但目前通常只使用ELF格式。其资料网上很哆可在Linux.old中寻找。还有网站www.nondot.org

请问内存地址的编码及bootsect.s编译链接后文件大小问题

    谢谢斑主及各位的指点,我好像理解地址编码了我简单地總结一下理解内容,请指正是否正确:
    在早期IBM PC机由于CPU外部地址总线是20位(即20条地址线其实在实模式下都是以20位寻址),因此决定最大寻址能仂为0-1MB而当时实际的内存 (RAM)最大仅为640KB,而640KB之后的地址则是其它硬件的编码地址其中包括显卡的显存,显卡ROM硬盘ROM地址,网卡地址其它扩展地     随着技术的不断发展,实际的内存容量已远远超出640KB为了向下兼容,真正的640KB之后到1024KB之间的384KB的内存地址要么简单地被系统屏蔽掉,要麼为了提高读取ROM效率将对应的硬件地址影射到内存的相对位置。
    至于在实模式下CPU内部以16位寻址而外部以20位寻址的相互转换确实需要再找相关资料了

}

我要回帖

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信