学习笔记
使用教材(配书源码以及使用方法)
《一个64位操作系统的设计与实现》
http://www.ituring.com.cn/book/2450
https://www.jianshu.com/p/28f9713a9171
源码结构
- 配书代码包 :第4章 \ 程序 \ 程序4-11
程序4-11 运行结果
[anno@localhost bootloader]$ make
nasm boot.asm -o boot.bin
nasm loader.asm -o loader.bin
[anno@localhost kernel]$ make
gcc -E head.S > head.s
as --64 -o head.o head.s
gcc -E entry.S > entry.s
as --64 -o entry.o entry.s
gcc -mcmodel=large -fno-builtin -m64 -c main.c
gcc -mcmodel=large -fno-builtin -m64 -c printk.c
gcc -mcmodel=large -fno-builtin -m64 -c trap.c
gcc -mcmodel=large -fno-builtin -m64 -c memory.c
gcc -mcmodel=large -fno-builtin -m64 -c interrupt.c
gcc -mcmodel=large -fno-builtin -m64 -c task.c
ld -b elf64-x86-64 -z muldefs -o system head.o entry.o main.o printk.o trap.o memory.o interrupt.o task.o -T Kernel.lds
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary system kernel.bin
[anno@localhost 4-11]$ sudo mount boot.img media -t vfat -o loop
[anno@localhost 4-11]$ sudo cp bootloader/loader.bin media
[anno@localhost 4-11]$ sync
[anno@localhost 4-11]$ sudo cp bootloader/boot.bin media
[anno@localhost 4-11]$ sync
[anno@localhost 4-11]$ sudo cp kernel/kernel.bin media
[anno@localhost 4-11]$ sync
[anno@localhost 4-11]$ bochs -f ./bochsrc

程序4-11 数据结构
各结构体大小

strcut mm_struct : 80 Bytes
struct thread_struct : 64 Bytes
struct task_struct : 88 Bytes
union task_union : 32768 Bytes
程序控制结构体 PCB(Process Control Block): task_struct (task.h)
struct task_struct
{
struct List list;
volatile long state;
unsigned long flags;
struct mm_struct *mm;
struct thread_struct *thread;
unsigned long addr_limit;
/*0x0000,0000,0000,0000 - 0x0000,7fff,ffff,ffff user*/
/*0xffff,8000,0000,0000 - 0xffff,ffff,ffff,ffff kernel*/
long pid;
long counter;
long signal;
long priority;
};
List 双向链表 用于连接各个PCB (lib.h)
struct List
{
struct List * prev;
struct List * next;
};
内存空间分布结构体: mm_struct (task.h)
struct mm_struct
{
pml4t_t *pgd; //page table point
unsigned long start_code,end_code;
unsigned long start_data,end_data;
unsigned long start_rodata,end_rodata;
unsigned long start_brk,end_brk;
unsigned long start_stack;
};
-
pml4t_t *pgd;
: CR3
pml4t_t (memory.h)
typedef struct {unsigned long pml4t;} pml4t_t;
thread_struct 用于保存执行现场的寄存器值 (task.h)
struct thread_struct
{
unsigned long rsp0; //in tss
unsigned long rip;
unsigned long rsp;
unsigned long fs;
unsigned long gs;
unsigned long cr2;
unsigned long trap_nr;
unsigned long error_code;
};
第一个进程 init_task_union
代码布局

联合体 task_union (task.h)
// 32KB
#define STACK_SIZE 32768
union task_union
{
struct task_struct task;
unsigned long stack[STACK_SIZE / sizeof(unsigned long)];
}__attribute__((aligned (8))); //8Bytes align
union task_union init_task_union
__attribute__((__section__ (".data.init_task")))
= {INIT_TASK(init_task_union.task)};
-
由联合体
task_union
的定义可见,是一个task_struct
结构体加一个数组
,之后声明创建了全局变量 init_task_union 作为操作系统的第一个进程 -
联合体内的数组空间,就作为这个进程init_task_union的栈空间来使用
-
task.h
是内核的一部分,更具体的说应该是内核代码段的一部分,这里联合里定义了一个数组仅仅只是定义,并没有在原地就开辟了一段空间出来给这个数组 -
union task_union init_task_union __attribute__((__section__ (".data.init_task"))) = {INIT_TASK(init_task_union.task)};
才是真正的开辟空间,而修饰__attribute__((__section__ (".data.init_task")))
意思就是把init_task_union这个联合体放到名为.data.init_task
的段里 -
结合程序4-11运行结果图,可以看到其栈基地址是
0x120000
,因为这个联合体的大小是32K= 32678=0x8000,那么就可以计算出.data.init_task
的段的起始地址0x1200000 - 0x8000 = 0x118000
-
同时看截图可以知道代码段的结束地址是
0x10b5e0
,很明显联合体init_task_union
不在代码段内 -
详细布局参见配书代码包
Kernel.lds
文件;
网友评论