Kernel.h 文件分析
關(guān)鍵成員變量
/** 物理內(nèi)存分配器 */
SplitAllocator *m_alloc;
/** 進(jìn)程管理器 */
ProcessManager *m_procs;
/** API管理器*/
API *m_api;
/** 針對(duì)當(dāng)前Core的Coreinfo */
CoreInfo *m_coreInfo;
/** CPU打斷管理器列表 */
Vector<List<InterruptHook *> *> m_interrupts;
/** 打斷管理器 */
IntController *m_intControl;
/** 計(jì)時(shí)器 */
Timer *m_timer;
構(gòu)造和析構(gòu)函數(shù)
-
kernel()
類的構(gòu)造函數(shù)
代碼中沒有實(shí)現(xiàn)方法恐锦,所以應(yīng)該是繼承父類的初始化方法來實(shí)現(xiàn) -
Kernel(CoreInfo *info)
自定義的構(gòu)造函數(shù)的實(shí)現(xiàn)
Kernel::Kernel(CoreInfo *info)
: Singleton<Kernel>(this), m_interrupts(256)
{
// 打印輸出
if (Log::instance)
{
Log::instance->append(BANNER);
Log::instance->append(COPYRIGHT "\r\n");
}
// 計(jì)算最大和最小的內(nèi)存
Memory::Range highMem;
Arch::MemoryMap map;
MemoryBlock::set(&highMem, 0, sizeof(highMem));
highMem.phys = info->memory.phys + map.range(MemoryMap::KernelData).size;
// 初始化成員變量
m_alloc = new SplitAllocator(info->memory, highMem);
m_procs = new ProcessManager(new Scheduler());
m_api = new API();
m_coreInfo = info;
m_intControl = ZERO;
m_timer = ZERO;
// 標(biāo)記kernel使用的內(nèi)存位置(前4MB的物理內(nèi)存)
for (Size i = 0; i < info->kernel.size; i += PAGESIZE)
m_alloc->allocate(info->kernel.phys + i);
// 標(biāo)記BootImage使用的內(nèi)存位置
for (Size i = 0; i < m_coreInfo->bootImageSize; i += PAGESIZE)
m_alloc->allocate(m_coreInfo->bootImageAddress + i);
// 儲(chǔ)存核心信道的內(nèi)存
for (Size i = 0; i < m_coreInfo->coreChannelSize; i += PAGESIZE)
m_alloc->allocate(m_coreInfo->coreChannelAddress + i);
// 清空打斷列表
m_interrupts.fill(ZERO);
}
3. `~kernel()` 析構(gòu)函數(shù)
### 處理CPU打斷事件處理
代碼定義了`void InterruptHandler(struct CPUState *state, ulong param)`函數(shù)來實(shí)現(xiàn)處理CPU打斷事件并且在此基礎(chǔ)上定義了名為`InterruptHook`的一個(gè)結(jié)構(gòu)體检眯,作為鉤子使用;
typedef struct InterruptHook
{
/**
* Constructor function.
* @param h Handler function for the hook.
* @param p Parameter to pass.
*/
InterruptHook(InterruptHandler *h, ulong p) : handler(h), param(p)
{
}
/**
* Comparision operator.
* @param i InterruptHook pointer.
* @return True if equal, false otherwise.
*/
bool operator == (InterruptHook *i)
{
return handler == i->handler && param == i->param;
}
/** Executed at time of interrupt. */
InterruptHandler *handler;
/** Passed to the handler. */
ulong param;
}
InterruptHook;
### 對(duì)象方法
根據(jù)FreeNOS Document的知道有一些比較重要的方法
1. `void Kernel::enableIRQ(u32 irq, bool enabled)`
打開或關(guān)閉硬件打斷(IRQ)功能, enabled is YES 打開艳馒。
2. `Kernel::Result Kernel::loadBootProcess(BootImage *image, Address imagePAddr, Size index)`
為BootProcess創(chuàng)建一個(gè)新的進(jìn)程
以下是該方法的實(shí)現(xiàn)方法:
Kernel::Result Kernel::loadBootProcess(BootImage *image, Address imagePAddr, Size index)
{
Address imageVAddr = (Address) image, args;
Size args_size = ARGV_SIZE;
BootSymbol *program;
BootSegment *segment;
Process *proc;
char *vaddr;
Arch::MemoryMap map;
// Point to the program and segments table
program = &((BootSymbol *) (imageVAddr + image->symbolTableOffset))[index];
segment = &((BootSegment *) (imageVAddr + image->segmentsTableOffset))[program->segmentsOffset];
// Ignore non-BootProgram entries
if (program->type != BootProgram)
return InvalidBootImage;
// Create process
proc = m_procs->create(program->entry, map);
if (!proc)
{
FATAL("failed to create boot program: " << program->name);
return ProcessError;
}
proc->setState(Process::Ready);
// Obtain process memory
MemoryContext *mem = proc->getMemoryContext();
// Map program segment into it's virtual memory
for (Size i = 0; i < program->segmentsCount; i++)
{
for (Size j = 0; j < segment[i].size; j += PAGESIZE)
{
mem->map(segment[i].virtualAddress + j,
imagePAddr + segment[i].offset + j,
Memory::User |
Memory::Readable |
Memory::Writable |
Memory::Executable);
}
}
// Map program arguments into the process
// TODO: move into the high memory???
m_alloc->allocateLow(args_size, &args);
mem->map(ARGV_ADDR, args, Memory::User | Memory::Readable | Memory::Writable);
// Copy program arguments
vaddr = (char *) m_alloc->toVirtual(args);
MemoryBlock::set(vaddr, 0, PAGESIZE);
MemoryBlock::copy(vaddr, program->name, ARGV_SIZE);
// Done
NOTICE("loaded: " << program->name);
return Success;
}