@qqiseeu
2013-11-23 09:45
64位Debian Sid下编译Linux 0.11内核
基本环境
- SMP Debian 3.11.6-1 (2013-10-27) x86_64 GNU/Linux
- gcc (Debian 4.8.2-5) 4.8.2
- GNU assembler (GNU Binutils for Debian) 2.23.90.20131116
- GNU ld (GNU Binutils for Debian) 2.23.90.20131116
1.修改Makefile及某些源文件
参考 Linux内核完全剖析 中p814—815的说明作相应的修改,具体为
(假设内核源代码位于linux-0.11-deb顶层目录下)
Makefile
- 将AS由 gas 改为 as , LD由 gld 改为 ld
- 将 linux-0.11-deb/Makefile 第34行中as的-c选项去除
- 将所有CFLAGS中的 -fcombine-regs 与 -mstring-insns 选项去除。
汇编程序
- 将boot/bootsect.s中的C语言风格注释(/*) 用!替换
- 将boot/下三个汇编程序的对齐指令由 .align n 改为 .align 2^n
- 将所有汇编程序(包括用asm关键字内联的)中引用的C变量前的下划线去掉
2.make过程中出现的问题
1.
as -o boot/head.o boot/head.s
boot/head.s: Assembler messages:
boot/head.s:43: Error: unsupported instruction `mov'
这是因为本机系统为64位,因此需要给所有Makefile中的as命令加上 --32 选项。类似地,根据GCC在线手册的说明 (见下方),需给所有Makefile中的CFLAGS加上 -m32 选项。
"The -m32 option sets int, long, and pointer types to 32 bits, and generates code that runs on any i386 system."
2.
init/main.c:23:29: error: static declaration of ‘fork’ follows non-static declaration
static inline _syscall0(int,fork)
include/unistd.h:134:6: note: in definition of macro ‘_syscall0’
type name(void) \
init/main.c:24:29: error: static declaration of ‘pause’ follows non-static declaration
static inline _syscall0(int,pause)
include/unistd.h:134:6: note: in definition of macro ‘_syscall0’
type name(void) \
include/unistd.h:224:5: note: previous declaration of ‘pause’ was here
int pause(void);
init/main.c:26:29: error: static declaration of ‘sync’ follows non-static declaration
static inline _syscall0(int,sync)
include/unistd.h:134:6: note: in definition of macro ‘_syscall0’
type name(void) \
include/unistd.h:235:5: note: previous declaration of ‘sync’ was here
int sync(void);
这是因为fork(), pause(), sync()在unistd.h中被声明为int类型,而在main.c中它们却被定义成了static inline int类型。(注意在内核代码中只有main.c中直接调用了了这三个函数) 可以用预处理指令的方法在main.c中屏蔽上述三个函数在unistd.h中的声明(似乎也可以用extern inline的方法修改这三个函数的定义来得到相同的效果,但是由于extern inline的特性比较奇怪,不推荐使用)。具体为:
在main.c中#include <unistd.h>
之前加上一句#define __IN_MAIN__
,然后用#ifndef
将fork、pause、sync在unistd.h中的声明包裹起来:
#ifndef __IN_MAIN__
int fork(void);
int pause(void);
int sync(void);
#endif
3.
In file included from fork.c:15:0:
fork.c: In function ‘copy_mem’:
../include/linux/sched.h:189:1: error: ‘asm’ operand has impossible constraints
__asm__("movw %%dx,%0\n\t" \
../include/linux/sched.h:211:28: note: in expansion of macro ‘_set_base’
#define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
fork.c:54:2: note: in expansion of macro ‘set_base’
set_base(p->ldt[1],new_code_base);
../include/linux/sched.h:189:1: error: ‘asm’ operand has impossible cons