FreeFlyOS 二 init部分詳解

2021-10-13 19:52:28 字數 3015 閱讀 1000

/*

* init.c : 建立臨時頁表,開啟分頁

*/#include "init.h"

#include "../mem/memlayout.h"

#include "../debug/debug.h"

/** 具體對映關係已經在kernel.ld中定義即,lma=vma-0xc0000000,故

* 只需將核心所在的位址寫入頁表,並開啟分頁即可。

*/extern unsigned int kernel_end;

void init()

init.h
#ifndef _init_h_

#define _init_h_

#include "../main/main.h"

#define vmm_page_size 0x1000

#define page_table_size 0x400

#define page_dir_size 0x400

#define page_mask 0xfffff000

#define vmm_page_present 0x1

#define vmm_page_rw 0x2

#define vmm_page_kernel 0x0

/**__attribute__( (section(".init.data") ) )將其設定為特定的.init.data節

*方便在鏈結指令碼中區分init部分和kernel部分

*/__attribute__( (section(".init.data") ) ) unsigned int pdt[page_dir_size]__attribute__( (aligned(vmm_page_size) ) );

__attribute__( (section(".init.data") ) ) unsigned int pt_init[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

//專門為vga裝置對映建立的頁表

__attribute__( (section(".init.data") ) ) unsigned int pt[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

//目前核心還不大,假定其大小不超過12mb,即三個頁表

__attribute__( (section(".init.data") ) ) unsigned int pt1[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

__attribute__( (section(".init.data") ) ) unsigned int pt2[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

__attribute__( (section(".init.data") ) ) unsigned int pt3[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

//__attribute__( (section(".init.data") ) ) unsigned int pt4[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

//核心棧大小為8kb,起始位址為0xf8000000,只需乙個頁表即可

__attribute__( (section(".init.data") ) ) unsigned int stack_pt[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

//user部分

__attribute__( (section(".init.data") ) ) unsigned int user_pt[page_table_size]__attribute__( (aligned(vmm_page_size) ) );

__attribute__( (section(".init.text") ) ) void init();

extern void main(void);

#endif

該檔案是為了核心**前開啟分頁,主要解決下面的問題:

在ld檔案中,我們必須確定核心**的vma(虛擬空間位址)和lma(物理空間位址),如果在這之前不開啟分頁,那麼核心**的虛擬位址和實體地址均是從16mb處開始,若在這之後開啟分頁,那麼整個虛擬位址空間就很難改變了(鏈結確定虛擬位址),所以會出錯。

現在的解決方案時,使用init.c建立乙個臨時頁表,並開啟分頁,然後把init**放在1mb處(vma和lma均為1mb),而核心**則放在vma=0xc1000000處,lma=0x01000000(16mb)處,因為不開啟分頁,那麼vma然後init**執行完畢,跳轉到核心**後,這部分就沒用了,所以直接新建乙個頁表,然後就可以刪除這部分**。

當然還有一種方案,就是qemu模擬器申請4gb記憶體,然後把vma和lma都放在0xc1000000處,在建立頁表後,就把核心移到0x01000000處,這種方法筆者也試過,但是當用模擬器申請4g記憶體時,3.5g以上是不可用的,所以這種方案在使用模擬器時不可取,當使用真機時可能有效,讀者們可以自行嘗試。

init部分主要功能就是建立臨時頁表,主要包括核心**部分和核心棧部分的對映,從下圖的elf檔案解析中我們可以看出需要3個頁目錄項,也就是12mb,才能包含bss段。

然後對映下核心棧,接著就把頁目錄表位址讀入cr3暫存器,需要注意的是,cr3暫存器儲存的都是實體地址,但由於init部分在鏈結指令碼中沒有指定虛擬位址,所以其虛擬位址=實體地址,接著開啟cr0暫存器的pg位,從而開啟分頁模式,然後將esp指標指向核心棧的棧頂,最後跳轉到核心的main函式,自此,init部分結束。

二個init方法

init方法是在servlet例項化之後執行的,並且只執行一次。類中有二個過載的方法,為什麼會有二個呢?一.先說init servletconfig 中引數servletconfig,代表的是配置資訊。即在web.xml中配置的資訊,比如 rdsdispatchservlet rdsdispatch...

Ghost blog 原始碼分析(二)Init

我能說很後悔四點鐘爬起來寫了個 一 config麼。在ghost blog的node server啟動後,首先做好config工作,接下來就是blog系統本身的初始化,在很多初始化步驟中,以筆者現在龜爬的閱讀進度來看,還不能理解為什麼,只能寫是什麼。在入口server.js中,首先呼叫了ghost....

專案二 第二部

1 使用vim編輯器配置網路 使用 setup 配置ip位址 service network restart 重新啟動網路服務 vim etc sysconfig network scripts ifcfg eth0 使用vim編輯器開啟網絡卡配置檔案 修改完相應的資訊後,按esc鍵,退出編輯模式,...