<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
<channel>
<title><![CDATA[MY1984 - 操作系统]]></title>
<link>http://www.my1984.com.cn/</link>
<description><![CDATA[长大的小孩～(迷走尘埃)]]></description>
<language>zh-cn</language>
<copyright><![CDATA[Copyright 2005 PBlog3 v2.8]]></copyright>
<webMaster><![CDATA[verywood@163.com(迷走尘埃)]]></webMaster>
<generator>PBlog2 v2.4</generator> 
<image>
	<title>MY1984</title>
	<url>http://www.my1984.com.cn/images/logos.gif</url>
	<link>http://www.my1984.com.cn/</link>
	<description>MY1984</description>
</image>

			<item>
			<link>http://www.my1984.com.cn/article.asp?id=940</link>
			<title><![CDATA[32位的操作系统只能支持4G内存吗？]]></title>
			<author>verywood@163.com(迷走尘埃)</author>
			<category><![CDATA[操作系统]]></category>
			<pubDate>Wed,30 Jun 2010 13:47:25 +0800</pubDate>
			<guid>http://www.my1984.com.cn/default.asp?id=940</guid>
		<description><![CDATA[通常的32位是不支持4G以上内存的，但是在服务器等的应用上，很早以前4G内存就已经不够用了，厂商们推出了一种叫做PAE（物理地址扩展）的技术，硬件支持加操作系统支持的话，启用PAE就可以实现32位模式下支持4G以上的内存。但是性能会有一定的下降，最大好像也只能支持扩展到8G，如果要了解更详细的可以百度搜索PAE。]]></description>
		</item>
		
			<item>
			<link>http://www.my1984.com.cn/article.asp?id=930</link>
			<title><![CDATA[(转)三个重要的系统表GDT、LDT和IDT(保护模式下)]]></title>
			<author>verywood@163.com(迷走尘埃)</author>
			<category><![CDATA[操作系统]]></category>
			<pubDate>Sat,29 May 2010 02:19:18 +0800</pubDate>
			<guid>http://www.my1984.com.cn/default.asp?id=930</guid>
		<description><![CDATA[这三个表是在内存中由操作系统或系统程序员所建，并不是固化在哪里，所以从理论上是可以被读写的。这三个表都是描述符表。描述符表是由若干个描述符组成，每个描述符占用8个字节的内存空间，每个描述符表内最多可以有8129个描述符。描述符是描述一个段的大小，地址及各种状态的。<br/>描述符表有三种,分别为全局描述符表GDT、局部描述符表LDT和中断描述符表IDT。<br/>1. 全局描述符表GDT：<br/>全局描述符表在系统中只能有一个,且可以被每一个任务所共享.任何描述符都可以放在GDT中,但中断门和陷阱门放在GDT中是不会起作用的.能被多个任务共享的内存区就是通过GDT完成的,<br/>2. 局部描述符表LDT:<br/>局部描述符表在系统中可以有多个,通常情况下是与任务的数量保持对等,但任务可以没有局部描述符表.任务间不相干的部分也是通过LDT实现的.这里涉及到地址映射的问题.和GDT一样,中断门和陷阱门放在LDT中是不会起作用的.<br/>3. 中断描述符表IDT:<br/>和GDT一样,中断描述符表在系统最多只能有一个,中断描述符表内可以存放256个描述符,分别对应256个中断.因为每个描述符占用8个字节,所以IDT的长度可达2K.中断描述符表中可以有任务门、中断门、陷阱门三个门描述符，其它的描述符在中断描述符表中无意义。<br/>4. 段选择子<br/>在保护模式下,段寄存器的内容已不是段值,而称其为选择子.该选择子指示描述符在上面这三个表中的位置,所以说选择子即是索引值。<br/>当我们把段选择子装入寄存器时不仅使该寄存器值，同时CPU将该选择子所对应的GDT或LDT中的描述符装入了不可见部分。这样只要我们不进行代码切换（不重新装入新的选择子）CPU就会不会对不可见部分存储的描述符进行更新，可以直接进行访问，加快了访问速度。一旦寄存器被重新赋值，不可见部分也将被重新赋值。<br/>关于选择子的值是否连续<br/>关于选择子的值，我认为不一定要连续。但是每个描述符的起始地址相对于第一个描述符（即空描述符）的首地址的偏移必须是8的倍数，即二进制最后三位为0。这样通过全局描述符表寄存器GDTR找到全局描述符表的首地址后，使用段选择子的高13位索引到正确的描述符表项（段选择子的高13位左移3位加上GDTR的值即为段选择子指定的段描述符的逻辑首地址）<br/>也就是说在两个段选择符之间可以填充能被8整除个字节值。当然，如果有选择子指向了这些填充的字节，一般会出错，除非你有意填充一些恰当的数值，呵呵。<br/>关于为什么LDT要放在GDT中<br/>LDT中的描述符和GDT中的描述符除了选择子的bit3一个为0一个为1用于区分该描述符是在GDT中还是在LDT中外，描述符本身的结构完全一样。开始我考虑既然是这样，为什么要将LDT放在GDT中而不是像GDT那样找一个GDTR寄存器呢？<br/>后来终于明白了原因——很简单，GDT表只有一个，是固定的；而LDT表每个任务就可以有一个，因此有多个，并且由于任务的个数在不断变化其数量也在不断变化。如果只有一个LDTR寄存器显然不能满足多个LDT的要求。因此INTEL的做法是把它放在放在GDT中。<br/>]]></description>
		</item>
		
			<item>
			<link>http://www.my1984.com.cn/article.asp?id=927</link>
			<title><![CDATA[虚拟地址如何得到物理地址]]></title>
			<author>verywood@163.com(迷走尘埃)</author>
			<category><![CDATA[操作系统]]></category>
			<pubDate>Sat,29 May 2010 02:13:24 +0800</pubDate>
			<guid>http://www.my1984.com.cn/default.asp?id=927</guid>
		<description><![CDATA[一个虚拟地址，大小4个字节(32bit)，包含着找到物理地址的信息，分为3个部分：<br/><br/>第22位到第31位这10位（最高10位）是页目录中的索引，第12位到第21位这10位是页表中的索引，第0位到第11位这12位（低12位）是页内偏移。<br/><br/>对于一个要转换成物理地址的虚拟地址，CPU首先根据CR3中的值，找到页目录所在的物理页。<br/><br/>然后根据虚拟地址的第22位到第31位这10位（最高的10bit)的值作为索引，找到相应的页目录项(PDE,page directory entry),页目录项中有这个虚拟地址所对应页表的物理地址。<br/><br/>有了页表的物理地址，根据虚拟地址的第12位到第21位这10位的值作为索引，找到该页表中相应的页表项(PTE,page table entry),页表项中就有这个虚拟地址所对应物理页的物理地址。<br/><br/>最后用虚拟地址的最低12位，也就是页内偏移，加上这个物理页的物理地址，就得到了该虚拟地址所对应的物理地址。]]></description>
		</item>
		
			<item>
			<link>http://www.my1984.com.cn/article.asp?id=820</link>
			<title><![CDATA[三级句柄表解析~看了一晚上]]></title>
			<author>verywood@163.com(迷走尘埃)</author>
			<category><![CDATA[操作系统]]></category>
			<pubDate>Wed,02 Dec 2009 01:43:15 +0800</pubDate>
			<guid>http://www.my1984.com.cn/default.asp?id=820</guid>
		<description><![CDATA[折腾了一晚上，晕，都1点多了...<br/>随便小记下：<br/>主要有两种，一种为全局的PspCidTable，一种为进程的句柄表。<br/><br/>一、PspCidTable<br/><img src="http://www.my1984.com.cn/attachments/month_0912/c200912211737.jpg" border="0" alt=""/><br/>这个获取对象简单<br/>知道CID<br/>CID&lt;0x800&nbsp;&nbsp; 直接 TableCode + CID*2 就可以了<br/>0x800&lt;CID&lt;0x1000&nbsp;&nbsp;*(PULONG)(TableCode + 4) + (CID-0x800)*2<br/>0x1000&lt;CID&nbsp;&nbsp;*(PULONG)(TableCode + 8) + (CID-0x1000)*2<br/><br/>二、进程句柄表<br/><img src="http://www.my1984.com.cn/attachments/month_0912/3200912212249.jpg" border="0" alt=""/><br/>判断 TableCode 末尾两位知道是几级句柄<br/>这里以二级为例：<br/>TableCode&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: 0xe1147001<br/>查找句柄号：1cdc = 0001 1100 1101 1100<br/>于是可以得到：<br/>第一层序号&nbsp;&nbsp; 100 1101 1100 = 4dc<br/>第二层序号&nbsp;&nbsp; 0 0011 = 3<br/>*(PULONG)(e1147000 + 3*4) = e2aa5000<br/>*(PULONG)(e2aa5000 + 4dc*2) = ca522da4<br/><span style="color:Red">ps1.第二层为什么*4，第一层为什么*2？<br/>因为第二第三层都是指针，每个四个字节，所以乘4<br/>第一层是句柄表项，为8个字节，本来应该*8的，但是句柄索引是按4递增的，也就是句柄都是4的倍数的。例如2号句柄就是8，所以相当于帮你乘了4，所以第一层只要*2。</span><br/><span style="color:Red">ps2.低三位清零再加上Object Header 大小，因为object header是8个字节对齐，低三位做标志位</span><br/>Object=object Header&amp;0xfffffff8+sizeof(Object Header)<br/>即 ca522da4&amp;0xfffffff8+0x18 = ca522db8&nbsp;&nbsp;就是目标对象结构了。<br/>可以用“ !object ca522db8”查看<br/><br/>三、两者差别<br/>1.PspCidTable中存放的对象是系统中所有的进线程对象指针,其索引就是PID和CID <br/>2.PspCidTable中存放是对象体(指向EPROCESS和ETHREAD),而每个进程私有的句柄表则存放的是对象头(OBJECT_HEADER)<br/>3.PspCidTable是一个独立的句柄表,而每个进程私有的句柄表以一个双链连接起来<br/><br/>四、原先看不懂得 ExpLookupHandleTableEntry<br/><div class="UBBPanel codePanel"><div class="UBBTitle"><img src="http://www.my1984.com.cn/images/code.gif" style="margin:0px 2px -3px 0px" alt="程序代码"/> 程序代码</div><div class="UBBContent">PHANDLE_TABLE_ENTRY<br/>NTAPI<br/>ExpLookupHandleTableEntry(IN PHANDLE_TABLE HandleTable,<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;IN EXHANDLE LookupHandle)<br/>{<br/>&nbsp;&nbsp;&nbsp;&nbsp;ULONG i, j, k, TableLevel, NextHandle;<br/>&nbsp;&nbsp;&nbsp;&nbsp;ULONG_PTR TableBase;<br/>&nbsp;&nbsp;&nbsp;&nbsp;PHANDLE_TABLE_ENTRY Entry = NULL;<br/>&nbsp;&nbsp;&nbsp;&nbsp;EXHANDLE Handle = LookupHandle;<br/>&nbsp;&nbsp;&nbsp;&nbsp;PUCHAR Level1, Level2, Level3;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/* Clear the tag bits and check what the next handle is */<br/>&nbsp;&nbsp;&nbsp;&nbsp;Handle.TagBits = 0;<br/>&nbsp;&nbsp;&nbsp;&nbsp;NextHandle = *(volatile ULONG*)&amp;HandleTable-&gt;NextHandleNeedingPool;<br/>&nbsp;&nbsp;&nbsp;&nbsp;if (Handle.Value &gt;= NextHandle) return NULL;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/* Get the table code */<br/>&nbsp;&nbsp;&nbsp;&nbsp;TableBase = *(volatile ULONG_PTR*)&amp;HandleTable-&gt;TableCode;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/* Extract the table level and actual table base */<br/>&nbsp;&nbsp;&nbsp;&nbsp;TableLevel = (ULONG)(TableBase &amp; 3);<br/>&nbsp;&nbsp;&nbsp;&nbsp;TableBase = TableBase - TableLevel;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/* Check what level we&#39;re running at */<br/>&nbsp;&nbsp;&nbsp;&nbsp;switch (TableLevel)<br/>&nbsp;&nbsp;&nbsp;&nbsp;{<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Direct index */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 0:<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Use level 1 and just get the entry directly */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Level1 = (PUCHAR)TableBase;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry = (PVOID)&amp;Level1[Handle.Value *<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (sizeof(HANDLE_TABLE_ENTRY) /<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SizeOfHandle(1))];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Nested index into mid level */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 1:<br/><span style="color:Red">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// A、B两处无非就是为了获取11-20位的值，j只是句柄除了 2^9？<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 因为在B处事按照一字节的指针操作的，所以相当于 /2^11 * 4<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 另外由于这里 Handle.Value -= i; 所以两者“直接除 2^9 还是 2^11在 * 4”<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 效果是一样的，因为第10、11位都是0了<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// C处就是获取低11位，同样道理，按照一字节的指针操作（PUCHAR）<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;&nbsp;&nbsp;&nbsp; 所以还 乘了 SizeOfHandle(1);&nbsp;&nbsp;&nbsp;&nbsp;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;*/</span><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Get the second table and index into it */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Level2 = (PUCHAR)TableBase;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i = Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Substract this index, and get the next one */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle.Value -= i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = Handle.Value /&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<strong> <span style="color:Red">★★★ A ★★★</span> </strong><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(SizeOfHandle(LOW_LEVEL_ENTRIES) / sizeof(PHANDLE_TABLE_ENTRY));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Now get the next table and get the entry from it */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Level1 = (PUCHAR)*(PHANDLE_TABLE_ENTRY*)&amp;Level2[j];&nbsp;&nbsp;<strong> <span style="color:Red">★★★ B ★★★</span> </strong><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry = (PVOID)&amp;Level1[i *<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (sizeof(HANDLE_TABLE_ENTRY) /<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SizeOfHandle(1))];&nbsp;&nbsp;&nbsp;&nbsp;<strong> <span style="color:Red">★★★ C ★★★</span> </strong><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Nested index into high level */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;case 2:<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Start with the 3rd level table */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Level3 = (PUCHAR)TableBase;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i = Handle.Value % SizeOfHandle(LOW_LEVEL_ENTRIES);<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Subtract this index and get the index for the next lower table */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Handle.Value -= i;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k = Handle.Value /<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(SizeOfHandle(LOW_LEVEL_ENTRIES) / sizeof(PHANDLE_TABLE_ENTRY));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Get the remaining index in the 2nd level table */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j = k % (MID_LEVEL_ENTRIES * sizeof(PHANDLE_TABLE_ENTRY));<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Get the remaining index, which is in the third table */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k -= j;<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;k /= MID_LEVEL_ENTRIES;<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Extract the table level for the handle in each table */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Level2 = (PUCHAR)*(PHANDLE_TABLE_ENTRY*)&amp;Level3[k];<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Level1 = (PUCHAR)*(PHANDLE_TABLE_ENTRY*)&amp;Level2[j];<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* Get the handle table entry */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Entry = (PVOID)&amp;Level1[i *<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (sizeof(HANDLE_TABLE_ENTRY) /<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SizeOfHandle(1))];<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;default:<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* All done */<br/>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;break;<br/>&nbsp;&nbsp;&nbsp;&nbsp;}<br/><br/>&nbsp;&nbsp;&nbsp;&nbsp;/* Return the handle entry */<br/>&nbsp;&nbsp;&nbsp;&nbsp;return Entry;<br/>}</div></div>]]></description>
		</item>
		
			<item>
			<link>http://www.my1984.com.cn/article.asp?id=812</link>
			<title><![CDATA[manifest文件介绍]]></title>
			<author>verywood@163.com(迷走尘埃)</author>
			<category><![CDATA[操作系统]]></category>
			<pubDate>Wed,25 Nov 2009 17:01:59 +0800</pubDate>
			<guid>http://www.my1984.com.cn/default.asp?id=812</guid>
		<description><![CDATA[一、Manifest<br/>Windows XP通过XML文件来实现这一功能，这些XML文件保存了有关应用程序配置的元数据，这里所说的XML文件，就是Manifest清单文件。<br/>Manifest事实上就是一个以.manifest为后缀的XML文件，用于组织和描述隔离应用程序及并行组件，其内部的信息如&lt;assemblyIdentity&gt;元素则标识着一个唯一的程序集，和其他信息一起，他们用于COM类、接口及库的绑定和激活，而这些信息，以往都是存储在注册表中的。另外，Manifests也制定了组成程序集的文件及Windows类。<br/><br/>二、Manifest的分类<br/>在Windows XP中，事实上是在.NET中，把Manifests分类为如下几种类型：<br/>1、程序集Manifests（Assembly Manifests）：主要用于描述程序集，管理程序集的名字、版本、资源、依赖程序集。其中共享程序集的Manifests存储在Windows的WinSxS目录中。私有的程序集Manifests则存可以作为一个资源存储在DLL中，也可以存储在应用程序目录下。<br/>2、应用程序Manifests（Application Manifests）：这类Manifests则用于描述隔离应用程序，它管理着此应用程序在运行时要绑定的共享的并行组件的名字、版本。该Manifests可以作为一个文件（.manifest文件）存储在应用程序相同的目录下，也可以作为一种资源嵌入在可执行文件内部(Embed Manifest)。<br/>3、应用程序配置文件（Application Configuration Files）：对于并行组件及隔离应用程序来说，使用这种Manifests来“Override and Redirect”所依赖程序集的版本。<br/>4、发行配置文件（Publisher Configuration Files）：用于重定向并行组件的版本倒另外一个合适的版本的Manifests。此时，被重定向的新程序集应该和原来的旧程序集具有相同的主.次（majou.minor）版本号。<br/><br/>三、Windows对于Manifest的处理<br/>XP以前版本的windows，会像以前那样执行这个exe文件，寻找相应的dll，没有分别，Manifest只是个多余的文件或资源，dll文件会直接到system32的目录下查找，并且调用。<br/>而XP及其以后的操作系统，则会首先读取Manifest，获得exe文件需要调用的DLL列表（此时获得的，并不直接是DLL文件的本身的位置，而是DLL的manifest）操作系统再根据DLL的Manifest提供的信息去寻找对应的DLL ，这样就可能区别不同版本的同一个DLL文件。<br/>这就说明了为什么我的程序可以在2000下面运行，而在XP及2003上无法运行。<br/>这也使得很多木马可以利用这个特点实现限制安全软件。<br/><br/>四、VS2005种的Manifest配置<br/>使用Visual Studio 2005以后的一个新问题是，VS2005带的8.0新版的C运行库(VC 8.0 CRT)文件在XP以后支持manifest的Windows版本中被调用时，将会check一下Application自身的Manifest，否则将会拒绝被调用，这也就是说，使用Visual Studio开发的Application，Manifest将是必不可少的（搞不懂MS为啥要这样设置，反正与VS2003.NET不同了，也许除了MS自己说的哪些冠冕堂皇的原因，至少这样一来Linux的Wine模拟要麻烦多了）<br/>不过，如果你的程序是静态链接的，没有使用dll，且只使用了操作系统核心的 Kernel32.dll, User32.dll, Ole32.dll, 或ShDocVW.dll 等，那么你可以不需要考虑Manifest， 可以关掉它。此时，在VS2005种中，project的设置必须是Use Standard Windows Libraries、Not Using ATL、No Common Language Runtime support ]]></description>
		</item>
		
			<item>
			<link>http://www.my1984.com.cn/article.asp?id=776</link>
			<title><![CDATA[银行家算法略解]]></title>
			<author>verywood@163.com(迷走尘埃)</author>
			<category><![CDATA[操作系统]]></category>
			<pubDate>Tue,27 Oct 2009 16:46:11 +0800</pubDate>
			<guid>http://www.my1984.com.cn/default.asp?id=776</guid>
		<description><![CDATA[无非就是系统避免死锁的一种典型算法<br/>原理感觉超级简单<br/>如果当前资源足够，也就是目前是安全状态，那么随意分配资源都不会引起死锁，但是如果出于非安全状态，那么如果某进程申请资源则看是否资源够，足够那么分配，进程处理完就会腾出资源<br/>如果不够那么退出这个进程的分配。下一个进程类似处理...<br/><br/>表达上感觉很无聊，⊙﹏⊙b汗 大菜比]]></description>
		</item>
		
</channel>
</rss>
