您的位置:首页 > 其它

关于自己写操作系统进程的实现

2016-06-29 21:21 369 查看
1.首先进程有进程表和相关数据结构:



typedef struct s_stackframe {
u32	gs;		/* \                                    */
u32	fs;		/* |                                    */
u32	es;		/* |                                    */
u32	ds;		/* |                                    */
u32	edi;		/* |                                    */
u32	esi;		/* | pushed by save()                   */
u32	ebp;		/* |                                    */
u32	kernel_esp;	/* <- 'popad' will ignore it            */
u32	ebx;		/* |                                    */
u32	edx;		/* |                                    */
u32	ecx;		/* |                                    */
u32	eax;		/* /                                    */
u32	retaddr;	/* return addr for kernel.asm::save()   */
u32	eip;		/* \                                    */
u32	cs;		/* |                                    */
u32	eflags;		/* | pushed by CPU during interrupt     */
u32	esp;		/* |                                    */
u32	ss;		/* /                                    */
}STACK_FRAME;

typedef struct s_proc {
STACK_FRAME regs;          /* process registers saved in stack frame */

u16 ldt_sel;               /* gdt selector giving ldt base and limit */
DESCRIPTOR ldts[LDT_SIZE]; /* local descriptors for code and data */
u32 pid;                   /* process id passed in from MM */
char p_name[16];           /* name of the process */
}PROCESS;
可以看出PROCESS结构体,将上面的图解释了一下,相当于我们根据上图来填PROCESS,

2.在初始化第一个进程的时候,一般设置较少,如下:

PUBLIC int kernel_main()
{
disp_str("-----\"kernel_main\" begins-----\n");

PROCESS* p_proc	= proc_table;

p_proc->ldt_sel	= SELECTOR_LDT_FIRST;
memcpy(&p_proc->ldts[0], &gdt[SELECTOR_KERNEL_CS>>3], sizeof(DESCRIPTOR));
p_proc->ldts[0].attr1 = DA_C | PRIVILEGE_TASK << 5;	// change the DPL
memcpy(&p_proc->ldts[1], &gdt[SELECTOR_KERNEL_DS>>3], sizeof(DESCRIPTOR));
p_proc->ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK << 5;	// change the DPL

p_proc->regs.cs	= (0 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
p_proc->regs.ds	= (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
p_proc->regs.es	= (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
p_proc->regs.fs	= (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
p_proc->regs.ss	= (8 & SA_RPL_MASK & SA_TI_MASK) | SA_TIL | RPL_TASK;
p_proc->regs.gs	= (SELECTOR_KERNEL_GS & SA_RPL_MASK) | RPL_TASK;
p_proc->regs.eip= (u32)TestA;
p_proc->regs.esp= (u32) task_stack + STACK_SIZE_TOTAL;
p_proc->regs.eflags = 0x1202;	// IF=1, IOPL=1, bit 2 is always 1.

p_proc_ready	= proc_table;
restart();

while(1){}
}
</pre><pre name="code" class="cpp">其中,eip即为我们的进程函数,函数名为TestA,在于渊的书中原函数如下:
</pre><pre name="code" class="cpp">void TestA()
{
int i = 0;
while(1){
disp_str("A");
disp_int(i++);
disp_str(".");
delay(1);
}
}



哈哈,其实就是一个操作而以,什么也没干,就是打印一个A,然后。。。。。。。

3.关键进程设置完后,什么时候进入进程,

      在上面kernel_main()函数后面,有一个restart()函数,内容如下:

restart:
mov	esp, [p_proc_ready]
lldt	[esp + P_LDT_SEL]
lea	eax, [esp + P_STACKTOP]
mov	dword [tss + TSS3_S_SP0], eax

pop	gs
pop	fs
pop	es
pop	ds
popad

add	esp, 4

iretd
,最后一个iretd执行以后,eflags会改变成pProc->regs.eflags的值,我们已经事先设置了IF位,所以进程开始运行了。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: