在 General Purpose OS 中,程式是由 OS 幫忙載入到記憶體中的,並且 OS 會負責為每個程式都建立一個 Virtual Address Space。這些程式的進入、結束以及與 kernel 溝通的 system call,是透過 User Library 來實作。
1
2
3
4
5
6
7
8
9
10
11
12
| SECTIONS
{
. = 0x0;
.text.entry : {*(text.entry) }
.text : { *(.text) }
.rodata : { *(.rodata) }
.data : {*(.data)}
.bss : {
. = ALIGN(16);
*(.bss*)
}
}
|
user library 幫我們進入到 main function 並在執行結束後 exit (system call)
1
2
3
4
5
6
| .section ".text.entry"
.global _user_entry
_user_entry:
bl main
bl exit
|
spec 要求實作一個簡易的 shell,shell 的實作基本上與 Lab 1 一致
1
2
3
4
5
6
7
8
9
10
| #include "user_lib.h"
#include "shell.h"
int main() {
while (1) {
char cmd[64];
shell_input(cmd);
shell_controller(cmd);
}
}
|
編譯 user_embed.elf 並將其與 kernel linking
由於 raw binary loader 無法取得 .bss 資訊,所以需要盡量避免非初始化 global 或 static variables 的情況,並在編譯過程加上 -fno-zero-initialized-in-bss
的 flag,使變數放在 .data
且 objcopy 後還會繼續留存
spec 的基本要求是實作一個 raw binary loader,加分題才會有 ELF loader
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| USER_CFLAGS = -Wall -Wextra -nostdlib -nostdinc -fno-zero-initialized-in-bss -fno-builtin-printf -fno-builtin-memcpy -Ilib -c -Werror
kernel8.img: $(SRC_OBJS_FILES) $(LIB_OBJS_FILES) user_embed.elf
$(LD) $(SRC_OBJS_FILES) $(LIB_OBJS_FILES) user_embed.elf -T $(SRC_DIR)/linker.ld -o kernel8.elf
$(OBJCPY) -O binary kernel8.elf kernel8.img
# build user library
$(BUILD_DIR)/user/%_c.o: $(USER_DIR)/%.c
mkdir -p $(@D)
$(CC) $(USER_CFLAGS) $< -o $@
$(BUILD_DIR)/user/%_asm.o: $(USER_DIR)/%.S
mkdir -p $(@D)
$(CC) $(USER_CFLAGS) $< -o $@
user_embed.elf: $(USER_OBJS_FILES) $(LIB_OBJS_FILES)
$(LD) $(USER_OBJS_FILES) $(LIB_OBJS_FILES) -T $(USER_DIR)/linker.ld -o user.elf
$(OBJCPY) -O binary user.elf user.img
$(LD) -r -b binary user.img -o user_embed.elf
|
$(LD) -r -b binary user.img -o user_embed.elf
會建立 3 個 symbols:
- _binary_user_img_start
- _binary_user_img_end
- _binary_user_img_size
.bss section:C 語言所種下的因