ucoreOS_lab1实验报告
操作系统镜像文件ucore.img是如何一步一步生成的?
# 构建bin/kernel
+ cc kern/init/init.c
+ cc kern/libs/readline.c
+ cc kern/libs/stdio.c
+ cc kern/debug/kdebug.c
+ cc kern/debug/kmonitor.c
+ cc kern/debug/panic.c
+ cc kern/driver/clock.c
+ cc kern/driver/console.c
+ cc kern/driver/intr.c
+ cc kern/driver/picirq.c
+ cc kern/trap/trap.c
+ cc kern/trap/trapentry.S
+ cc kern/trap/vectors.S
+ cc kern/mm/pmm.c
+ cc libs/printfmt.c
+ cc libs/string.c
+ ld bin/kernel
# 构建sign工具与bin/bootblock
+ cc boot/bootasm.S
+ cc boot/bootmain.c
+ cc tools/sign.c
# 使用gcc编译器由tools/sign.c生成可执行文件bin/sign
gcc -Itools/ -g -Wall -O2 -c tools/sign.c -o obj/sign/tools/sign.o
gcc -g -Wall -O2 obj/sign/tools/sign.o -o bin/sign
# 使用ld命令链接/boot/bootasm.o、obj/boot/bootmain.o到obj/bootblock.o
+ 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: 472 bytes
build 512 bytes boot sector: 'bin/bootblock' success!
# 构建ucore.img
dd if=/dev/zero of=bin/ucore.img count=10000 # 使用dd工具创建一个bin/ucore.img空文件
10000+0 records in
10000+0 records out
5120000 bytes (5.1 MB) copied, 0.149355 s, 34.3 MB/s
dd if=bin/bootblock of=bin/ucore.img conv=notrunc # 使用dd工具将文件bin/bootblock写入bin/ucore.img, 参数conv=notrunc表示不截断输出文件
1+0 records in
1+0 records out
512 bytes (512 B) copied, 0.0003161 s, 1.6 MB/s
dd if=bin/kernel of=bin/ucore.img seek=1 conv=notrunc # 使用dd工具将文件bin/kernel写入bin/ucore.img起始的1个block后,即bootblock后, 参数seek=1表示从输出文件开头跳过1个block开始写入
146+1 records in
146+1 records out
74923 bytes (75 kB) copied, 0.00279755 s, 26.8 MB/s
第一步.编译16个内核文件,构建出内核 bin/kernel
生成 bin/bootblock引导程序
{
编译bootasm.S,bootmain.c,链接obj/bootblock.o
编译sign.c生成sign.o工具
使用sign.o工具规范化bootblock.o,生成bin/bootblock引导扇区
}
生成ucore.img虚拟磁盘
{
dd初始化为5120000bytes,内容为0的文件
dd拷贝bin/bootblock到ucore.img第一个扇区
dd拷贝bin/kernel到ucore.img第二个扇区往后的空间
}
这个逻辑与一般的操作系统很类似
一个被系统认为是符合规范的硬盘主引导扇区的特征是什么?
上文中的sign.o工具可以规范化bootblock.o,生成bin/bootblock引导扇区。因此查看sign.c源代码内容即可
sign.c在tools里面
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
struct stat st;
// 输入状态判断
if (argc != 3) {
fprintf(stderr, "Usage: <input filename> <output filename>\n");
return -1;
}
// 读取文件头
if (stat(argv[1], &st) != 0) {
fprintf(stderr, "Error opening file '%s': %s\n", argv[1], strerror(errno));
return -1;
}
// 问题1中输出的文件大小
printf("'%s' size: %lld bytes\n", argv[1], (long long)st.st_size);
// 文件大小超过510字节报错返回,因为最后2个字节要用作结束标志位
if (st.st_size > 510) {
fprintf(stderr, "%lld >> 510!!\n", (long long)st.st_size);
return -1;
}
// 多余位用0填充
char buf[512];
memset(buf, 0, sizeof(buf));
FILE *ifp = fopen(argv[1], "rb");
int size = fread(buf, 1, st.st_size, ifp);
// 文件实际大小需和文件头描述一致
if (size != st.st_size) {
fprintf(stderr, "read '%s' error, size is %d.\n", argv[1], size);
return -1;
}
fclose(ifp);
buf[510] = 0x55;
buf[511] = 0xAA;
// 写入结束位
FILE *ofp = fopen(argv[2], "wb+");
size = fwrite(buf, 1, 512, ofp);
if (size != 512) {
fprintf(stderr, "write '%s' error, size is %d.\n", argv[2], size);
return -1;
}
fclose(ofp);
printf("build 512 bytes boot sector: '%s' success!\n", argv[2]);
return 0;
}
硬盘主引导扇区的特征为
大小为512字节
文件内容不超过510bytes
最后2bytes为0x55 0xAA