<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<atom:link href="http://gentoo-zh.org/extern.php?action=feed&amp;tid=293&amp;type=rss" rel="self" type="application/rss+xml" />
		<title><![CDATA[Gentoo中文社区 / 进程表的定义与初始化]]></title>
		<link>http://www.gentoo-zh.org/viewtopic.php?id=293</link>
		<description><![CDATA[进程表的定义与初始化 最近发表的帖子。]]></description>
		<lastBuildDate>Fri, 26 Aug 2022 05:58:45 +0000</lastBuildDate>
		<generator>FluxBB</generator>
		<item>
			<title><![CDATA[进程表的定义与初始化]]></title>
			<link>http://www.gentoo-zh.org/viewtopic.php?pid=299#p299</link>
			<description><![CDATA[<p>PROCESS* p_proc=proc_table;</p><p>&#160; &#160; p_proc---&gt;ldt_sel=SELECTOR_LDT_FIRST;&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; </p><p>&#160; &#160; //设置进程表中进程的ldt_sel,ldt_sel被赋值SELECTOR_LDT_FIRST,这个宏的定义在代码6-1-中</p><p>&#160; &#160; memcpy(&amp;p_proc-&gt;ldts[0], &amp;gdt[SELECTOR_KERNEL_CS &gt;&gt; 3], sizeof(DESCRIPTOR));&#160; //将SELECTOR_KERNEL_CS所指的描述符拷贝到进程PCB的ldts[0]处<br />&#160; &#160; p_proc-&gt;ldts[0].attr1 = DA_C | PRIVILEGE_TASK &lt;&lt; 5;&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; // change the DPL<br />&#160; &#160; memcpy(&amp;p_proc-&gt;ldts[1], &amp;gdt[SELECTOR_KERNEL_DS &gt;&gt; 3], sizeof(DESCRIPTOR)); //将SELECTOR_KERNEL_DS所指的描述符拷贝到进程PCB的ldts[1]处<br />&#160; &#160; p_proc-&gt;ldts[1].attr1 = DA_DRW | PRIVILEGE_TASK &lt;&lt; 5;&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; // change the DPL</p><p>&#160; &#160; //LDT中共有两个描述符，分别被初始化为内核代码段和内核数据段，只是改变了一下DPL，以让其运行在低特权级下(2)<br />&#160; &#160; p_proc-&gt;regs.cs&#160; = ((8 * 0) &amp; SA_RPL_MASK &amp; SA_TI_MASK) | SA_TIL | RPL_TASK;&#160; &#160; //8*0和8*1是选择子，而且是进程PCB中的LDT描述符的选择子。<br /> //cs指向LDT中的第一个描述符 (3) 通过cs中的这个描述符跳转到内核代码段<br /> //LDT选择子是从0开始的。一个描述符相隔8个字节，所以要乘以8<br />&#160; &#160; p_proc-&gt;regs.ds&#160; = ((8 * 1) &amp; SA_RPL_MASK &amp; SA_TI_MASK) | SA_TIL | RPL_TASK;&#160; &#160; //根据选择子的属性确定是全局选择子还是LDT选择子。 <br />&#160; &#160; p_proc-&gt;regs.es&#160; = ((8 * 1) &amp; SA_RPL_MASK &amp; SA_TI_MASK) | SA_TIL | RPL_TASK;&#160; &#160; //本例会根据cs中的选择子自动到进程PCB中读取LDT描述符<br />&#160; &#160; p_proc-&gt;regs.fs&#160; = ((8 * 1) &amp; SA_RPL_MASK &amp; SA_TI_MASK) | SA_TIL | RPL_TASK;&#160; &#160; //本例比较特殊的地方是进程LDT描述符在进程PCB中，没有固定的LDT段<br />&#160; &#160; p_proc-&gt;regs.ss&#160; = ((8 * 1) &amp; SA_RPL_MASK &amp; SA_TI_MASK) | SA_TIL | RPL_TASK;</p><p>&#160; &#160; //ds，es，fs，ss指向LDT中的第二个描述符<br />&#160; &#160; p_proc-&gt;regs.gs&#160; = (SELECTOR_KERNEL_GS &amp; SA_RPL_MASK) | RPL_TASK;</p><p>&#160; &#160; //gs指向显存，只是其RPL发生改变<br />&#160; &#160; p_proc-&gt;regs.eip = (u32)TestA;</p><p>&#160; &#160; //eip指向TestA，这表明进程将从TestA的入口地址开始运行<br />&#160; &#160; p_proc-&gt;regs.esp = (u32) task_stack + STACK_SIZE_TOTAL;</p><p>&#160; &#160; //esp指向单独的堆栈，堆栈大小为STACK_SIZE_TOTAL<br />&#160; &#160; p_proc-&gt;regs.eflags = 0x1202; // IF=1, IOPL=1, bit 2 is always 1.</p><p>&#160; &#160; //eflags=0x1202,恰巧设置了IF位，并把IOPL设为1，这样，进程就可以使用I/O指令，并且中断会在iretd执行时，被打开。</p><p>&#160; &#160; //代码中使用到的宏，基本在protect.h中</p><p>&#160; &#160; p_proc_ready = proc_table;</p><br /><br /><br /><p>这里要记得把LDT跟GDT是联系在一起的，别忘了填充GDT中进程的LDT的描述符。protect.c</p><p> init_descriptor(</p><p>&#160; &#160;&amp;gdt[INDEX_LDT_FIRST],&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;//设置填充地址位置（GDT中的LDT描述符 ） <br />&#160; &#160;vir2phys(seg2phys(SELECTOR_KERNEL_DS),&#160; proc_table[0].ldts),&#160; //LDT基址,这个GDT中的LDT基址指向proc_table[0].ldts&#160; &#160; &#160; &#160;(1)<br />&#160; &#160;LDT_SIZE * sizeof(DESCRIPTOR) - 1,&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;//LDT大小</p><p>&#160; &#160;DA_LDT);&#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160; &#160;//LDT属性</p><p>&#160; &#160;seg2phys(SELECTOR_KERNEL_DS)把段地址转换为物理地址，把DS右移几位。</p><p>&#160; &#160;vir2phys为宏定义，在protect.h中</p><p>&#160; &#160;#define vir2phys(seg_base, vir)&#160; &#160; &#160; (u32)(((u32)seg_base) + (u32)(vir))</p>]]></description>
			<author><![CDATA[dummy@example.com (batsom)]]></author>
			<pubDate>Fri, 26 Aug 2022 05:58:45 +0000</pubDate>
			<guid>http://www.gentoo-zh.org/viewtopic.php?pid=299#p299</guid>
		</item>
	</channel>
</rss>
