引言1、 工作背景研究linux-0.11已有月余,代码看了好几遍,虽然能看懂,却总感觉如隔靴搔痒一般。这当然是正常的,毕竟不是自己写的东西,毕竟这是个操作系统。但若能亲自修改并调试一番,对其的理解就能更加深刻了。然而在linux-0.11的编译要在装有gcc1.4的系统里进行,那个系统太老了,修改起来也不方便,又没法安装源码阅读器. . . 那能不能在Ubuntu下用高版本的gcc编译并运行呢?2、 工作意义简单讲下本文所描述工作以及撰写本文的意义吧。Linux-0.11在高版本gcc-4.6.11下编译调试并能正常运行可以使学习linux-0.11更加方便、容易,也为进一步研究linux2.6奠定基础。更加重要的是,本项工作的过程其实就是一个深入学习的过程,对了解新旧版本gcc之间的差异、linux内核运行机制、linux调试方法有很大帮助。另外,对于linux-0.11在高版本gcc下的编译工作,网上已有不少先驱者,但大都没能让编译过后的os正常运行起来,偶有高人完成,也未能提供足够的调试材料,这让不少初学者对此失去了兴趣。现在有兴趣于此的大哥mm们High起来吧!当然这项工作在很多人眼里并没多重要,他们认为它一没有科研创新价值,而没有商业盈利价值,还耗费不少时间,他们有更重要的事情去做。这个浮躁的社会里,人们做什么事情总要讲究足够的理由。对此我只能说,你们是没错的。然我道中人终究还有不少,撰写本文也是希望跟我相同想法的人能从中获得他们需要的帮助,并借此与他们互相勉励一下。有句老话怎么说来着?重要的不是目的地,而是沿途的风景。当然若有高人前辈路过,愿意批评指正的,望不吝赐教,我将不甚感激涕零。3、工作目的: 本文工作的目的在ubuntu-11中使用gcc-4.61成功编译linux-0.11源码,并经过调试使之能正常运行。由于时间关系,并未解决系统中所有存在的bug,十分遗憾,若有大哥mm们愿继续完成,我将非常高兴。虽如此,拥有了在这个过程中学到的这些东西,我的工作已有足够的意义。本文的特点是图文并茂,对错误原因解释详细,关键地方有对linux一些机制的阐述,尽量减少读者的理解障碍。代码包来源:赵炯博士网站http://oldlinux.org/Linux.old中下载bochs安装文件、linux-0.11.tar.Z源码包、linux-0.11-devel-040923.zip源码包(该源码在gcc1.4下编译通过,作为对照使用)。平台搭建:我使用的环境是VirtualBox中安装ubuntu-11,与win7共享工作文件夹(其中存有linux-0.11源码),win7中使用editplus和source insight进行源码的编辑和阅读。
一、编译过程对linux-0.11在高版本gcc下的编译过程,网上也有一些散碎材料,赵炯博士的论坛里和《linux内核完全剖析》中也有一部分介绍。本节依据先后顺序将编译过程中每个错误的解决方法依次完整地罗列出来。1、除错工具:(1)sourceInsight,源码阅读器肯定需要了,否则岂不是找崩溃吗?(2)internet,编译过程网上有不少人完成了,赵炯博士也完成了,对于一些问题可以查到相应资料。(3)editplus,这是个编辑器了,我用之多年,比较喜欢,其特点就是小但功能全。2、问题及解决方法问题1: 第一次make会出现如图1.1所示的问题。图1.1 这是注释方式问题 ,as86不支持/**/,改为每行前面用!注释。问题2:再次make后出现如图1.2所示的错误。图1.2 修改所有makefile文件的编译器修改一下,将gas,gld改成as和ld,所有AS的选项参数去掉-c(as不用这个选项),gcc的选项参数去掉-fcombine-regs -mstring-insns(这两个参数现在的gcc不支持了)。问题3:接着又出现如图1.3所示的编译错误。图1.3 这是新旧版本gcc对齐的表达方式不同所造成的,.align n n改为 2
n便可。
问题4:接着又出现如图1.4所示的编译错误。图1.4上面的错误只有static declaration of ‘pause’ follows non-static declaration这类是必须修改的,查看main.c和unistd.h发现产生错误的原因:Main.c中有如图1.5所示的语句:图1.5而unistd.h文件中有图1.6所示的声明语句:图1.6Main.c头部包含了unistd.h,那么关于fork、pause、sync系统调用的声明就重复了,不知道为什么旧版本的gcc可以编译通过,需要详查,在main.c中增加这些函数的内联声明的原因是linux-0.11的进程0和1共用一个栈,进程0在创建了进程1后只有等待pause的功能,为了避免进程1栈中数据被破坏, 进程0不可使用栈,那么就不可使用call来调用fork和pause库函数,而应该用内联的方法,防止参数传递将栈搞乱。
修改这个问题的方法可以利用条件宏的预处理作用来进行。在main.c开始包含#define _IN_MAIN,而unistd.h中的声明做如图1.7所示修改即可。图1.7问题5:Make后又发现如图1.8所示的错误。图1.8这是编译器对嵌入式汇编已用过的寄存器声明无效的报错信息。查看源文件发现问题出现在_set_base宏这里。在 include/linux/sched.h中,有如下语句:
188 #define _set_base(addr,base)
189 __asm__("movw %%dx,%0
"
190 "rorl $16,%%edx
"
191 "movb %%dl,%1
"
192 "movb %%dh,%2"
193 ::"m" (*((addr)+2)),
194 "m" (*((addr)+4)),
195 "m" (*((addr)+7)),
196 "d" (base)
197 :"dx") //无效声明 去掉197行中的:"dx"这项。也即197行变成了:197 )然后去掉所有汇编中的类似的地方:String.h,memory.c,buffer.c,super.c(原因是Bitmap.c)。这是由于as不断改进,目前自动化程度越来越高,不用人工指定一个变量需要的寄存器了,所以代码中的 __asm__("ax")需要全部去掉。如bitmap.c和namei.c。问题6:Make后又发现如图1.9所示的错误。图1.9查看segment.h 有如图1.10所示代码。图1.10将r改为q,该问题就解决了。r表示使用任意动态分配的寄存器,q表示使用动态分配字节可寻址寄存器(eax,ebx,ecx或edx)。问题7:Make后又发现如图1.11所示的错误。图1.11这是个左值问题,查看exec.c源码如图1.12所示:图1.12这个写法确实有些别扭,使用get_free_page()申请新页面,页面指针pag指向新页面,申请不到空闲页面则返回0。如图1.13修改便可。图1.13 类似问题在malloc.c中也有。问题8:Make后又发现如图1.14所示的错误。图1.14查看代码blk.h发现是#elif木有判断的逻辑表达式,改为#elif 1便可。问题9:Make后又发现如图1.15所示的错误。图1.15这个问题不懂怎么改,按照之间类似问题将第三个冒号后面的寄存器删掉也不行,求指点。这里我果断把所有汇编注释掉,因为strtok这个函数在内核中没有被调用。至此,编译问题全部解决。
在Ubuntu 10.10下安装SimpleScalarUbuntu中Terminal和GNOME文件管理器的互通方法相关资讯 Linux资料
- Linux触发连锁反应,惠及全球 (04/25/2012 05:49:29)
- 【Linux】pam常用模块及意义 (04/18/2012 09:42:50)
- 【Linux】配置Apache的别名的pam认 (04/18/2012 09:40:21)
| - 如何挂载只读的Linux文件系统 (04/19/2012 06:10:57)
- 【Linux】ftp服务的ftpusers黑名单 (04/18/2012 09:42:02)
- 返璞归真的Linux BFS调度器 (04/14/2012 10:54:07)
|
本文评论 查看全部评论 (0)