mirror of https://github.com/kiukotsu/ucore.git
175 lines
12 KiB
Markdown
175 lines
12 KiB
Markdown
### 练习一
|
||
|
||
---
|
||
|
||
lab1中包含一个bootloader和一个OS。这个bootloader可以切换到X86保护模式,能够读磁盘并加载ELF执行文件格式,并显示字符。而这lab1中的OS只是一个可以处理时钟中断和显示字符的幼儿园级别OS。
|
||
|
||
**问题一**:操作系统镜像文件 ucore.img 是如何一步一部生成的?(需要比较详细的解释 Makefile 中每一条相关命令和命令参数的含义,以及说明命令导致的结果)
|
||
|
||
**回答**:在 `labcodes/lab1` 目录下运行 `make "V="` 得到如下结果:
|
||
|
||
```shell
|
||
# 编译 init.c 文件,生成 init.o
|
||
+ cc kern/init/init.c
|
||
gcc -Ikern/init/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/init/init.c -o obj/kern/init/init.o
|
||
|
||
# 编译 stdio.c 文件,生成 stdio.o
|
||
+ cc kern/libs/stdio.c
|
||
gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/stdio.c -o obj/kern/libs/stdio.o
|
||
|
||
# 编译 readline.c 文件,生成 readline.o
|
||
+ cc kern/libs/readline.c
|
||
gcc -Ikern/libs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/libs/readline.c -o obj/kern/libs/readline.o
|
||
|
||
# 编译 panic.c 文件,生成 painc.o
|
||
+ cc kern/debug/panic.c
|
||
gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/panic.c -o obj/kern/debug/panic.o
|
||
|
||
# 编译 kdebug.c 文件,生成 kdebug.o
|
||
+ cc kern/debug/kdebug.c
|
||
gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kdebug.c -o obj/kern/debug/kdebug.o
|
||
|
||
# 编译 kmonitor.c 文件,生成 kmonitor.o
|
||
+ cc kern/debug/kmonitor.c
|
||
gcc -Ikern/debug/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/debug/kmonitor.c -o obj/kern/debug/kmonitor.o
|
||
|
||
# 编译 clock.c 文件,生成 clock.o
|
||
+ cc kern/driver/clock.c
|
||
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/clock.c -o obj/kern/driver/clock.o
|
||
|
||
# 编译 console.c 文件,生成 console.o
|
||
+ cc kern/driver/console.c
|
||
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/console.c -o obj/kern/driver/console.o
|
||
|
||
# 编译 picirq.c 文件,生成 picirq.o
|
||
+ cc kern/driver/picirq.c
|
||
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/picirq.c -o obj/kern/driver/picirq.o
|
||
|
||
# 编译 intr.c 文件,生成 intr.o
|
||
+ cc kern/driver/intr.c
|
||
gcc -Ikern/driver/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/driver/intr.c -o obj/kern/driver/intr.o
|
||
|
||
# 编译 trap.c 文件,生成 trap.o
|
||
+ cc kern/trap/trap.c
|
||
gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trap.c -o obj/kern/trap/trap.o
|
||
|
||
# 编译 vectors.S 生成 vectors.o
|
||
+ cc kern/trap/vectors.S
|
||
gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/vectors.S -o obj/kern/trap/vectors.o
|
||
|
||
# 编译 trapentry.S 生成 trapentry.o
|
||
+ cc kern/trap/trapentry.S
|
||
gcc -Ikern/trap/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/trap/trapentry.S -o obj/kern/trap/trapentry.o
|
||
|
||
# 编译 pmm.c 生成 pmm.o
|
||
+ cc kern/mm/pmm.c
|
||
gcc -Ikern/mm/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Ikern/debug/ -Ikern/driver/ -Ikern/trap/ -Ikern/mm/ -c kern/mm/pmm.c -o obj/kern/mm/pmm.o
|
||
|
||
# 编译 string.c 生成 string.o
|
||
+ cc libs/string.c
|
||
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -c libs/string.c -o obj/libs/string.o
|
||
|
||
# 编译 printfmt.c 生成 printfmt.o
|
||
+ cc libs/printfmt.c
|
||
gcc -Ilibs/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -c libs/printfmt.c -o obj/libs/printfmt.o
|
||
|
||
# 链接生成的所有目标文件,并生成 kernel 二进制文件
|
||
+ ld bin/kernel
|
||
ld -m elf_i386 -nostdlib -T tools/kernel.ld -o bin/kernel obj/kern/init/init.o obj/kern/libs/stdio.o obj/kern/libs/readline.o obj/kern/debug/panic.o obj/kern/debug/kdebug.o obj/kern/debug/kmonitor.o obj/kern/driver/clock.o obj/kern/driver/console.o obj/kern/driver/picirq.o obj/kern/driver/intr.o obj/kern/trap/trap.o obj/kern/trap/vectors.o obj/kern/trap/trapentry.o obj/kern/mm/pmm.o obj/libs/string.o obj/libs/printfmt.o
|
||
|
||
# 编译 bootasm.S / bootmain.c / sign.c /
|
||
+ cc boot/bootasm.S
|
||
gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootasm.S -o obj/boot/bootasm.o
|
||
+ cc boot/bootmain.c
|
||
gcc -Iboot/ -fno-builtin -Wall -ggdb -m32 -gstabs -nostdinc -fno-stack-protector -Ilibs/ -Os -nostdinc -c boot/bootmain.c -o obj/boot/bootmain.o
|
||
+ cc tools/sign.c
|
||
gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
|
||
|
||
# 生成 sign 文件
|
||
gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign
|
||
|
||
# 链接生成 bootblock 二进制文件
|
||
+ ld bin/bootblock
|
||
ld -m elf_i386 -nostdlib -N -e start -Ttext 0x7C00 obj/boot/bootasm.o obj/boot/bootmain.o -o obj/bootblock.o
|
||
'obj/bootblock.out' size: 488 bytes
|
||
build 512 bytes boot sector: 'bin/bootblock' success!
|
||
|
||
# 生成ucore.img 文件
|
||
dd if=/dev/zero of=bin/ucore.img count=10000
|
||
10000+0 records in
|
||
10000+0 records out
|
||
5120000 bytes (5.1 MB, 4.9 MiB) copied, 0.0242314 s, 211 MB/s
|
||
dd if=bin/bootblock of=bin/ucore.img conv=notrunc
|
||
1+0 records in
|
||
1+0 records out
|
||
512 bytes copied, 9.9196e-05 s, 5.2 MB/s
|
||
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc
|
||
146+1 records in
|
||
146+1 records out
|
||
74828 bytes (75 kB, 73 KiB) copied, 0.000607019 s, 123 MB/s
|
||
```
|
||
|
||
> 注意:上面显示的编译过程,我删去了一些警告信息。只将有用的信息标记出来。
|
||
|
||
**GCC** [编译选项](https://gcc.gnu.org/onlinedocs/gcc/C-Dialect-Options.html#C-Dialect-Options)详解:
|
||
|
||
| 编译选项 | 含义 |
|
||
| :--------------------- | :----------------------------------------------------------: |
|
||
| `-I` | 指定库文件包含路径(① 指定值 ② 环境变量 ③ 标准系统搜索路径) |
|
||
| `-fno-builtin` | 只识别以 `__builtin_`为前缀的 GCC 內建函数,禁用大多数內建函数,防止与其重名 |
|
||
| `-Wall` | 编译后显示所有[警告信息](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html#Warning-Options) |
|
||
| `-ggdb` | 使用 GDB 加入[调试信息](https://gcc.gnu.org/onlinedocs/gcc/Debugging-Options.html#Debugging-Options) |
|
||
| `-m32` | 生成 32位机器代码,`int long pointer` 都是 32 位,指定[x86处理器特定选项](https://gcc.gnu.org/onlinedocs/gcc/x86-Options.html#x86-Options), [处理器依赖选项](https://gcc.gnu.org/onlinedocs/gcc/Submodel-Options.html#Submodel-Options) |
|
||
| `-gstabs` | 产生 stabs 格式的调试信息,不包含 GDB 扩展 |
|
||
| `-nostdinc` | 不搜索标准系统目录的头文件,只搜索 `-I / -iquote / -isystem / -dirafter`指定的头文件, [目录选项](https://gcc.gnu.org/onlinedocs/gcc/Directory-Options.html#Directory-Options) |
|
||
| `-fno-stack-protector` | 禁用堆栈保护机制,[工具选项](https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html#Instrumentation-Options) |
|
||
| `-c` | 编译或汇编源文件,但是不进行链接。将`.c/.i/.s`等后缀的文件编译成 `.o` 后缀。[输出类型控制](https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#Overall-Options) |
|
||
| `-O` | 优化生成的代码,`-Os` 仅仅是优化生成代码的大小,它开启了所有的`-O2`优化选项,除了那些会使代码尺寸增大的选项。 [优化选项](https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html#Optimize-Options) |
|
||
|
||
**LD** [编译选项](https://sourceware.org/binutils/docs-2.31/ld/Options.html#Options)详解:
|
||
|
||
| 编译选项 | 含义 |
|
||
| ------------------------------------- | :----------------------------------------------------------: |
|
||
| `-m` | 指定生成文件的格式,默认使用 `LDEMULATION`环境变量,如果没有这个环境变量,则依赖与linker 的默认配置。通过 `ld -V` 可以查看它支持的 `emulation`。 |
|
||
| `-nostdlib` | 只搜索命令行中显示制定的库目录,链接脚本里面制定的目录被忽略,包括命令行中制定的链接脚本。 |
|
||
| `-N` | 设置 `text and data section` 可读写,数据段不进行页对其,不链接动态链接库 |
|
||
| `-e entry` | 指定程序开始执行的入口函数,而不是默认的入口点。 |
|
||
| `-Tbss=org / -Tdata=org / -Ttext=org` | 通过 `org` 制定一个 `section` 在输出文件中的绝对地址。 |
|
||
| | |
|
||
|
||
**dd** [磁盘维护命令](http://www.runoob.com/linux/linux-comm-dd.html)详解:
|
||
|
||
```
|
||
Linux dd命令用于读取、转换并输出数据。dd可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。
|
||
|
||
if = 文件名:输入文件名,缺省为标准输入。
|
||
of = 文件名:输出文件名,缺省为标准输出。
|
||
ibs = bytes:一次读入bytes个字节,即指定一个块大小为bytes个字节。(默认 512 字节)
|
||
obs = bytes:一次输出bytes个字节,即指定一个块大小为bytes个字节。(默认 512 字节)
|
||
bs = bytes:同时设置读入/输出的块大小为bytes个字节。
|
||
cbs = bytes:一次转换bytes个字节,即指定转换缓冲区大小。
|
||
skip = blocks:从输入文件开头跳过blocks个块后再开始复制。
|
||
seek = blocks:从输出文件开头跳过blocks个块后再开始复制。
|
||
count = blocks:仅拷贝blocks个块,块大小等于ibs指定的字节数。
|
||
conv = <关键字>,关键字可以有以下11种:
|
||
conversion:用指定的参数转换文件。
|
||
ascii:转换ebcdic为ascii
|
||
ebcdic:转换ascii为ebcdic
|
||
ibm:转换ascii为alternate ebcdic
|
||
block:把每一行转换为长度为cbs,不足部分用空格填充
|
||
unblock:使每一行的长度都为cbs,不足部分用空格填充
|
||
lcase:把大写字符转换为小写字符
|
||
ucase:把小写字符转换为大写字符
|
||
swab:交换输入的每对字节
|
||
noerror:出错时不停止
|
||
notrunc:不截短输出文件
|
||
sync:将每个输入块填充到ibs个字节,不足部分用空(NUL)字符补齐。
|
||
|
||
N and BYTES may be followed by the following multiplicative suffixes:
|
||
c =1, w =2, b =512, kB =1000, K =1024, MB =1000*1000, M =1024*1024, xM =M
|
||
GB =1000*1000*1000, G =1024*1024*1024, and so on for T, P, E, Z, Y.
|
||
```
|
||
|
||
**问题二**:一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?
|
||
|
||
**回答**:硬盘主引导扇区的 size = 512 Bytes,并且最后两个字节为`0x55AA`。 |