Linux 环境下编译 0.11版本内核 kernel

http://linux.chinaitlab.com/soft/878778_2.html


linux 0.11 0.11kernel下来尝试编译一 把。

 

linux-0.11.tar.gz 下载地址:

 

 

1 tar xvfz linux-0.11.tar.gz

2 cd linux-0.11

3 make

make: as86: Command not finded

 

make: ***

 

as86 汇编器未安装

 

 

yum install dev86* (请务必保证网络畅通,如果使用Debian Linux系统命令改为 apt-get install dev86*

 

下载dev86-0.16.3-8.i386.rpm安装 下载 http://www.oldlinux.org/Linux.old/study/tools/

 

4 make

 

gas -c -o boot/head.o boot/head.s

 

make: gas: Command not finded

 

make: *** [boot/head.o] Error 127

 

gas 汇编器未安装

 

 

yum install binutils* (请确保网络正常)

 

binutils-2.20.tar.gz安装 下载地址http://ftp.gnu.org/gnu/binutils/

tar xvfz binutils-2.20.tar.gz

./configure

make

make install

 

Gnu assembler 已经安装

which as

/usr/local/bin/as

 

5 make

 

gas -c -o boot/head.o boot/head.s

make: gas: Command not found

make: *** [boot/head.o] Error 127

 

gasgld GNU assembler的名称是 as

 

 

Makefile 文件

 

AS =gas 修改为 AS =as

LD =gld 修改为 LD =ld

 

6make

 

as -c -o boot/head.o boot/head.s

as: unrecognized option '-c'

make: *** [boot/head.o] Error 1

 

as 语法和1991

 

 

Makefile 文件

 

$(AS) -c -o $*.o $< $(AS) -o $*.o $<

 

7make

 

as -o boot/head.o boot/head.s

boot/head.s: Assembler messages:

boot/head.s:231: Error: alignment not a power of 2

make: *** [boot/head.o] Error 1

 

.align 2 是汇编语言指示符,其含义是指存储

“2”22^2),即按4

GNU as直接是写出对齐的值而非2

 

.align 2 .align 4

.align 3 .align 8

 

 

boot/head.s 文件

 

.align 2 应该改为 .align 4

.align 3 .align 8

 

8make

 

cc1: error: unrecognized command line option "-mstring-insns"

cc1: error: unrecognized command line option "-fcombine-regs"

make: *** [init/main.o] Error 1

 

 

Makefile 文件

 

-fcombine-regs -mstring-insns

 

9make

 

In file include from init/main.c:9:

include/unistd.h:207: warning: function return types not compatible due to 'volatile'

include/unistd.h:208: warning: function return types not compatible due to 'volatile'

init/main.c:24: error: static declaration of 'fork' follows non-static declaration

init/main.c:26: error: static declaration of 'pause' follows non-static declaration

include/unistd.h:224: note: previous declaration of 'pause' was here

init/main.c:30: error: static declaration of 'sync' follows non-static declaration

include/unistd.h:235: note: previous declaration of 'sync' was here

init/main.c:108: warning: return type of 'main' is not 'int'

make: *** [init/main.o] Error 1

 

 

init/main.c 文件

 

static inline _syscall0(int,fork) inline _syscall0(int,fork)

static inline _syscall0(int,pause) 修改为 inline _syscall0(int,pause)

static inline _syscall1(int,setup,void *,BIOS) 修改为 inline _syscall1(int,setup,void *,BIOS)

static inline _syscall0(int,sync) 修改为 inline _syscall0(int,sync)

 

10make

 

(cd kernel; make)

make[1]: Entering directory '***/linux-0.11/kernel'

gcc -Wall -O -fstrength-reduce -fomit-frame-pointer -fcombine-regs -finline-functions -mstring-insns -nostdinc -I../include \

-c -o sched.o sched.c

cc1: error: unrecognized command line option "-mstring-insns"

cc1: error: unrecognized command line option "-fcombine-regs"

make[1]: *** [sched.o] Error 1

make[1]: Leaving directiory '***/linux-0.11/kernel'

make: *** [kernel/kernel.o] Error 2

 

 

kernel目录下 Makefile 文件

 

-fcombine-regs -mstring-insns

 

11make

 

gas -c -o system_call.o system_call.s

make[1]: gas: Command not found

make[1]: *** [system_call.o] Error 127

make[1]: Leaving directory '***/linux-0.11/kernel'

make: *** [kernel/kernel.o] Error 2

 

 

kernel目录下 Makefile 文件

 

AS =gas 修改为 AS =as

LD =gld 修改为 LD =ld

$(AS) -c -o $*.o $< $(AS) -o $*.o $<

 

12make

 

fork.c:In function 'copy_process':

fork.c:121: warning: suggest parentheses around assignment used as truth value

fork.c:In function 'copy_mem':

fork.c:54: error: can't find a register in class 'DREG' while reloading 'asm'

fork.c:55: error: can't find a register in class 'DREG' while reloading 'asm'

fork.c:46: error: 'asm' operand has impossible constraints

fork.c:47: error: 'asm' operand has impossible constraints

fork.c:54: error: 'asm' operand has impossible constraints

fork.c:55: error: 'asm' operand has impossible constraints

make[1]: *** [fork.o] Error 1

make[1]: Leaving directory '***/linux-0.11/kernel'

make: *** [kernel/kernel.o] Error 2

 

kernel/fork.c 54

 

set_base(p->ldt[1],new_code_base);

include/linux/sched.h 188 —— 211 行:

 

set_base 的实现

 

#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )

 

#define _set_base(addr,base) \

__asm__("movw %%dx,%0\n\t" \

"rorl $16,%%edx\n\t" \

"movb %%dl,%1\n\t" \

"movb %%dh,%2" \

::"m" (*((addr)+2)), \

"m" (*((addr)+4)), \

"m" (*((addr)+7)), \

"d" (base) \

:"dx")

 

为这里涉及到汇编的知识,哥卡在这里一直没解决并且郁闷了好久,最后只好看回《linux内核0.11 http://www.oldlinux.org/Linux.old/kernel/0.1x/ 这里提供了修改 linux-0.11-060618-gcc4.tar.gz 好的 0.11

 

Beyond Compare

 

#define _set_base(addr,base) \ #define _set_base(addr,base) \

__asm__("movw %%dx,%0\n\t" \ __asm__("push %%edx\n\t" \

"rorl $16,%%edx\n\t" \ "movw %%dx,%0\n\t" \

"movb %%dl,%1\n\t" \ "rorl $16,%%edx\n\t" \

"movb %%dh,%2" \ "movb %%dl,%1\n\t" \

::"m" (*((addr)+2)), \ "movb %%dh,%2\n\t" \

"m" (*((addr)+4)), \ "pop %%edx" \

"m" (*((addr)+7)), \ ::"m" (*((addr)+2)), \

"d" (base) \ "m" (*((addr)+4)), \

:"dx") "m" (*((addr)+7)), \

"d" (base) )

 

#define switch_to(n) {\

struct {long a,b;} __tmp; \

__asm__("cmpl %%ecx,_current\n\t" \

"je 1f\n\t" \

"movw %%dx,%1\n\t" \

"xchgl %%ecx,_current\n\t" \

"ljmp %0\n\t" \ ------------------------------ "ljmp *%0\n\t" \

"cmpl %%ecx,_last_task_used_math\n\t" \

"jne 1f\n\t" \

"clts\n" \

"1:" \

::"m" (*&__tmp.a),"m" (*&__tmp.b), \

"d" (_TSS(n)),"c" ((long) task[n])); \

}

 

#define _get_base(addr) ({\ static inline unsigned long _get_base(char * addr)

unsigned long __base; \ {

__asm__("movb %3,%%dh\n\t" \ unsigned long __base;

movb %2,%%dl\n\t" \ __asm__("movb %3,%%dh\n\t" \

shll $16,%%edx\n\t" \ "movb %2,%%dl\n\t" \

movw %1,%%dx" \ "shll $16,%%edx\n\t" \

"=d" (__base) \ "movw %1,%%dx" \

"m" (*((addr)+2)), \ :"=&d" (__base) \

"m" (*((addr)+4)), \ :"m" (*((addr)+2)), \

"m" (*((addr)+7))); \ "m" (*((addr)+4)), \

__base;}) "m" (*((addr)+7)));

return __base;

}

 

GNU as汇编器不断进化的原因,需要将 *.s 文件中

.globl _idt,_gdt,_pg_dir,_tmp_floppy_area

.globl idt,gdt,pg_dir,tmp_floppy_area

 

boot/head.o: In function 'setup_idt':

(.text+0x87): undefined reference to '_idt'

boot/head.o: In function 'idt_descr':

(.text+0x54ac): undefined reference to '_idt'

kernel/kernel.o: In function 'sched_init':

(.text+0x37c): undefined reference to '_idt'

 

 

GCC中基本的内联汇编:__asm____volatile__("InstructionList");

 

__asm__(

"movl $1,%eax\r\t"

"xor %ebx,%ebx\r\t"

"int $0x80"

);

 

带有C/C++表达式的内联汇编:

 

__asm__ __volatile__("InstructionList"

:Output

:Input

:Clobber/Modify);

 

4个部分都不是必须的,任何一个部分都可以为空,其规则为:

 

1、如果Clobber/Modify 为空,则其前面的冒号(:)必须省略。

 

2、如果OutputInputClobber/Modify都为空,OutputInput之前的冒号(:)既可以省略,也可以不省略。

 

3、如果InputClobber/Modify为空,但Output不为空,Input前的冒号(:)既可以省略,也可以不省略。

 

4、如果后面的部分不为空,而前面的部分为空,则前面的冒号(:)都必须保留,否则无法说明不为空的部分究竟是第几部分。

 

 

 

每一个InputOutput表达式都必须指定自己的操作约束Operation Constraint,这里将讨论在80386平台上所可能使用的操作约束。

 

当前的输入或输出需要借助一个寄存器时,需要为其指定一个寄存器约束,可以直接指定一个寄存器的名字。

 

常用的寄存器约束的缩写

约束 意义

r 表示使用一个通用寄存器,由 GCC %eax/%ax/%al,%ebx/%bx/%bl,%ecx/%cx/%cl,%edx/%dx/%dl中选取一个GCC认为合适的。

g 表示使用任意一个寄存器,由GCC在所有的可以使用的寄存器中选取一个GCC认为合适的。

q 表示使用一个通用寄存器,和约束r的意义相同。

a 表示使用%eax/%ax/%al

b 表示使用%ebx/%bx/%bl

c 表示使用%ecx/%cx/%cl

d 表示使用%edx/%dx/%dl

D 表示使用%edi/%di

S 表示使用%esi/%si

f 表示使用浮点寄存器

t 表示使用第一个浮点寄存器

u 表示使用第二个浮点寄存器

 

如果一个Input/Output 操作表达式的C/C++表达式表现为一个内存地址,不想借助于任何寄存器,则可以使用内存约束。比如:

__asm__("lidt%0":"=m"(__idt_addr));

__asm__("lidt%0"::"m"(__idt_addr));

 

 

 

修饰符 输入/输出 意义

= O 表示此Output操作表达式是Write-Only的。

+ O 表示此Output操作表达式是Read-Write的。

& O 表示此Output操作表达式独占为其指定的寄存器。

% I 表示此Input 操作表达式中的C/C++表达式可以和下一 个Input操作表达式中的C/C++表达式互换

 

--------------------------------------------------------------------------------------------------------------------------------------------------------------

 

13make

 

In file included from stat.c:13:

../include/asm/segment.h: Assembler messages:

../include/asm/segment.h:27: Error: bad register name '%sil'

make[1]: *** [stat.o] Error 1

make[1]: Leaving directory '***/linux-0.11/fs'

make: *** [fs/fs.o] Error 2

 

出错原因:

 

fs 目录下的 Makefile 中编译选项使用了 -O 优化选项导致寄存器错误

 

 

解决方法:

 

fs目录下的Makefile 文件中的

CFLAGS =-Wall -O -fstrength-reduce -fomit-frame-pointer \

修改为

CFLAGS =-Wall -fstrength-reduce -fomit-frame-pointer \

 

14make

 

tools/build.c: In function 'main':

tools/build.c:75: warning: implicit declaration of function 'MAJOR'

tools/build.c:76: warning: implicit declaration of function 'MINOR'

tmp/ccsMKTAS.o: In function 'main':

build.c:(.text+0xe1): undefined reference to 'MAJOR'

build.c:(.text+0xf7): undefined reference to 'MINOR'

collect2: ld returned 1 exit status

 

出错原因:'MAJOR' 'MINOR' 未定义

 

解决办法:

 

我们可以在 include/linux/fs.h 文件中找到

 

#define MAJOR(a) (((unsigned)(a))>>8)

#define MINOR(a) ((a)&0xff)

 

而在 tools/build.c 中也有包含 #include

那么再看第一层目录中的主 Makefile 文件

 

tools/build: tools/build.c

$(CC) $(CFLAGS) \

-o tools/build tools/build.c

 

好象确实没有引用头文件

 

简单的添加 -Iinclude

重新编译后出现一堆报标准C库头文件的错误

 

再添加 -nostdinc

又报 stderr fprintf 之类的错误

 

没折,只好将

#define MAJOR(a) (((unsigned)(a))>>8)

#define MINOR(a) ((a)&0xff)

添加到 tools/build.c 文件中,然后删除 #include

 

15make

 

make[1]: Leaving directory '***/linux-0.11/lib'

ld -s -x -M boot/head.o init/main.o \

kernel/kernel.o mm/mm.o fs/fs.o \

kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \

kernel/math/math.a \

lib/lib.a \

-o tools/system > System.map

ld: warning: cannot find entry symbol _start; defaulting to 08048a0

gcc -Wall -O -fstrength-reduce -fomit-frame-pointer \

-o tools/build tools/build.c

tools/build boot/bootsect boot/setup tools/system /dev/hd6 > Image

/dev/hd6: No such file or directory

Couldn't stat root device.

make: *** [Image] Error 1

 

解决办法:

 

将第一层主 Makefile 文件中的

 

tools/system: boot/head.o init/main.o \

$(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)

$(LD) $(LDFLAGS) boot/head.o init/main.o \

$(ARCHIVES) \

$(DRIVERS) \

$(MATH) \

$(LIBS) \

-o tools/system > System.map

 

修改为

 

tools/system: boot/head.o init/main.o \

$(ARCHIVES) $(DRIVERS) $(MATH) $(LIBS)

$(LD) $(LDFLAGS) boot/head.o init/main.o \

$(ARCHIVES) \

$(DRIVERS) \

$(MATH) \

$(LIBS) \

-o tools/system

nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)'| sort > System.map

 

nm命令将目标文件中的各种符号列出来。

 

 

ROOT_DEV=/dev/hd6 修改为 ROOT_DEV=

 

16make

 

/DISCARD/

*(.note.GNU-stack)

*(.gnu_debuglink)

*(.gnu.lto_*)

OUTPUT(tools/system elf32-i386)

nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)'| sort > System.map

nm: tools/system: no symbols

gcc -Wall -O -fstrength-reduce -fomit-frame-pointer \

-o tools/build tools/build.c

tools/build boot/bootsect boot/setup tools/system > Image

Root device is (3, 6)

Boot sector 512 bytes.

Setup is 312 bytes.

Non-Gcc header of 'system'

make: *** [Image] Error 1

 

解决办法:

 

将第一层主 Makefile 文件中的

 

LDFLAGS =-s -x -M

修改为

LDFLAGS =-m elf_i386 -Ttext 0 -e startup_32

 

 

Image: boot/bootsect boot/setup tools/system tools/build

tools/build boot/bootsect boot/setup tools/system $(ROOT_DEV) > Image

sync

修改为

Image: boot/bootsect boot/setup tools/system tools/build

objcopy -O binary -R .note -R .comment tools/system tools/kernel

tools/build boot/bootsect boot/setup tools/kernel $(ROOT_DEV) > Image

rm tools/kernel -f

sync

 

objcopy命令能复制和转化目标文件

objcopy -O binary -R .note -R .comment tools/system tools/kernel

-O binary tools/system tools/kernel tools/system 生成二进制文件 tools/kernel

-R .note -R .comment 删除 .note段 和 .comment

 

 

tools/build.c 文件中的

if (((long *) buf)[5] != 0)

die("Non-GCC header of 'system'");

这段代码注释掉

//if (((long *) buf)[5] != 0)

// die("Non-GCC header of 'system'");

 

17make

 

ld -m elf_i386 -Ttext 0 -e startup_32 boot/head.o init/main.o \

kernel/kernel.o mm/mm.o fs/fs.o \

kernel/blk_drv/blk_drv.a kernel/chr_drv/chr_drv.a \

kernel/math/math.a \

lib/lib.a \

-o tools/system

nm tools/system | grep -v '\(compiled\)\|\(\.o$$\)\|\( [aU] \)\|\(\.\.ng$$\)\|\(LASH[RL]DI\)'| sort > System.map

gcc -Wall -O -fstrength-reduce -fomit-frame-pointer \

-o tools/build tools/build.c

objcopy -O binary -R .note -R .comment tools/system tools/kernel

tools/build boot/bootsect boot/setup tools/system > Image

Root device is (3, 6)

Boot sector 512 bytes.

Setup is 312 bytes.

System is 128323 bytes.

rm tools/kernel -f

sync

 

终于编译 linux 内核 0.11 版本成功了!

 

 

 

最 后也可以利用赵炯博士在http://www.oldlinux.org/Linux.old/kernel/0.1x/ 这里提供了修改 linux-0.11-060618-gcc4.tar.gz 好的 0.11版本的内核进行编译,只要修改以下 Makefile -mcpu=i386 -march=i386 还需要将 kernel/blk_drv/blk.h 文件第87行 将 #elif 修改为 #else 就可以编译通过了。

 

 

总结:编译需要一个过程,学习也是同样需要一个过程。虽然可以利用赵博士修改好的 kernel-0.11 版快速的编译内核,但是那样就不会遇到太多有价值的编译问题,而解决这些问题就是一个学习过程,相信赵博士在编译0.11版本内核的时候也遇到了这些问 题。这样我想起了高中解数学难题的时候,高手解体时总是省略了一些因式分解的过程,而对于菜鸟来说这些省略的过程是非常重要的。

 

/* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-fareast-font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;}
<script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"2","bdMiniList":false,"bdPic":"","bdStyle":"0","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
阅读(4419) | 评论(1) | 转发(4) |
给主人留下些什么吧!~~

uubuge2014-02-27 23:15:28

写得非常好,大多数我遇到的困难都让你写在里面了,楼主能否给我发一个你修改好的源码包,我到现在还没编译过去,quejing@163.com

评论热议
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
带中文注释可成功编译运行的Linux0.11+Bochs2.62实验环境说明 此注释以网上获得的“linux带中文注释的0.11版本”为基础,对照赵炯博士《Linux内核完全注释(0.11) 》V3.0版(http://oldlinux.org/download/clk011c-3.0.pdf)编辑而成。作为对赵博士感谢,以及对Linux初学者的回馈,特发布在CSDN上。 此注释可以在http://oldlinux.org/Linux.old/bochs/提供的Linux-0.11-devel-XXXXXX实验环境下正确编译成功,使用:"make disk"命令重启Bochs虚拟机后,新编译源码直接生效,便于学习者直接阅读源码,直接进行实验。 注意事项: 1、为了使注释版与实验环境上的Linux0.11内核保持一致,达到对应文件可以互换的目的,与Linux0.11原始版本相比,加入了15个系统调用函数(参见include/Linux/sys.h第78-92行。赵博士原书没有这部分注释,我不敢班门弄斧),其它相关的文件加入了相应的定义。新加入的代码只有函数体定义,没有具体实现,对其它原始代码没有改变、没有影响。 2、键盘定义改成了美式键盘(原始代码中是芬兰键盘,会导致个别键出问题,调试的时候我曾被迷糊了好久,以为自己把程序搞乱了)。 3、把网上VC版的注释统一改成了 “/* */” 格式的注释。经测试,在Linux0.11实验环境中(gcc1.40),只有标准C注释语法可以正常编译。 4、由于《Linux内核完全注释(0.11) 》原书版本更新的原因,注释中提到的图、表可能与V3.0版书中不一致。 5、由于代码中加入注释,代码行号发生变化,注释中提到的代码行号会出现不一致,建议对照3.0版查询对应内容。 6、实验方法:请先安装附带的Bochs2.62版安装包,双击Test.bxrc即可启动实验系统,执行命令:sh t,即可完成对linuxcn的编译。 7、linux目录中是此实验系统中/usr/src/linux提取出来的不含中文注释的linux0.11源码(此版本比原始的0.11版多15个系统调用函数),linuxcn是加入了中文注释的源码。 8、diskb.img是实验系统与Windows环境下进行文件交换的1.44M软盘映像,执行脚本命令"sh t"时会自动从此映像中读取linux.tar、linuxcn.tar包,解包并编译编译结果在:/usr/root/zw/linuxcn目录下。为了方便文件交换,建议使用7zip为压缩/解压缩工具(7zip可以直接生成tar包),用WinImage实现Windows环境与软件映像交换文件。 9、实验系统下 .profile中加入了几个命令,请读者注意。 10、若实验环境的启动盘被破坏,请用压缩包中的bootimage-0.11-hd覆盖对应文件即可。 11、若实验环境的要命文件系统被破坏,请用压缩包中的hdc-0.11-new.img覆盖对应文件即可。 2014-5-4 cyfx2288

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值