网站地图    收藏   

主页 > 后端 > 网站安全 >

内核之旅 解开系统神秘的面纱 - Windows操作系统

来源:自学PHP网    时间:2015-04-17 18:33 作者: 阅读:

[导读] 内核之旅 揭开系统神秘的面纱(上)好的资料可以给大家带来技术上面更多的想法,《深入解析Windows操作系统》是一本以Linux系统为基础讲解OS架构与硬件关系的图书,对于喜欢Linux的朋友...

内核之旅 揭开系统神秘的面纱(上)

 

好的资料可以给大家带来技术上面更多的想法,《深入解析Windows操作系统》是一本以Linux系统为基础讲解OS架构与硬件关系的图书,对于喜欢Linux的朋友可以考虑阅读该书,在《Unix操作系统设计》中由于以Unix V为版本讲解的Unix系统,多少有些许看得不尽人意的地方;而目前针对FreeBSD的资料比较少,所以如果大家想从整个系统的角度来分析一个类Unix系统的话,这本书将是一个好资料,而且还会帮你纠正很多写代码的弊病。

  如果说Intel出了汇编语言,那么《80x86汇编语言与计算机体系结构》则是告诉你汇编程序是怎么编写的,每个指令在何种情况下占用了几个字节,一个程序在编译、连接后的opcode(机器码)是如何产生的,作者会很细心的告诉你一个mov指令占用一个时钟周期,在数据传值上经常使用mov、xchg,还会告诉你mov指令占用的opcode字节。

  (一)需要理解的几个概念

  在开始针对Windows的机制分析前,需要注意一些基础概念,有了这些概念,然后结合工具的使用,会有利于对Windows机制的分析。

  API:Application Program Interface,应用程序接口,系统中有几千个API函数。

  Plat software Development Kit:平台开发套间,在开发VC程序时,最好的习惯是安装最新的SDK包,里面的内容绝对比你安装过时的MSDN多很多,同时还有很多例子代码告诉你Windows程序的规范是怎么写的。

  DDK:设备驱动开发包。

  进程的概念:

  进程只是一个容器而已,因为这个容器用来存放主线程,在Windows程序中,无论是main、WinMain函数创建的都不是进程,而是主线程,主线程才为一个进程内的主体。理解线程的概念,对于开发Windows程序有很大的帮助。进程创建后,根据其各种环境条件创建了主线程,主线程也分为两个部分,User Mode Thread(用户模式线程)和Kernel Mode Thread(内核模式线程)。对于主线程而言,我们可做的坏事情(从线程角度考虑,抛弃进程的各种环境条件)不是很多,当我们调用CreateThread函数创建一个线程,或者创建一个线程池时,我们可以做的坏事情就会相对较多,因为MS提供了一部分管理线程的函数,同时也公布了一组管理线程的内核数据结构,该数据结构为CONTEXT;从CONTEXT数据结构是依靠CPU类型来看,该结构的确是有些底层了;对于该结构的描述,在《Windows核心编程》有所阐述。通过初始化一个CONTEXT结构,通过GetThreadContext函数可以获取当前线程的CPU寄存器状态,通过SetThreadContext函数我们可以设置当前线程的CPU寄存器状态。不过这里有些麻烦的是,当我们使用GetThreadContext和SetThreadContext函数时,线程必须是不活动的,因为一个用户态可见的活动线程是异步执行的,可能你使用上述函数时得到的值与实际值有出入。前段时间在搞线程池时问过同事关于异步的问题,同事给我了很好的答案,通过一段时间的编写测试代码,对该处有了更深的认识。

  线程的概念:

  有必要把下面的内容单独出来,上面只是通过主线程的一些看法,以及CONTEXT结构的特殊性。既然谈及到CONTEXT结构,有个比较有意思的事情,我昨天早上起床背了几个单词后突然想起了这个结构,于是我把ntoskrnl.exe进行了逆向,在ntoskrnl.exe内也存在一个CONTEXT结构,而且与用户态的结构值完全相同,但这并不说明内核态会引用用户态的该结构,前面提及的该结构底层的说法只是说明该结构保存获得的内容比较底层而已。如果大家认真看过《Windows核心编程》中关于对该结构描述时,作者夸张的做法后,其实作者有些地方也不是很对的,当然每个人理解技术的情况不同,如果这里解释有误,还是需要大家的指点。

  提及CONTEXT结构,而且上面也提及可以通过Get(Set)ThreadContext函数实现对该结构的修改,那么我们是否可以实现通过对该结构的操作来实现用户态下线程的暂停和恢复运行?答案是可以,但是需要进行特殊的处理,因为线程是异步执行的,其堆栈环境也不象进程那样稳定,换句话说进程只要主线程在运行,那么其堆栈环境会稳定的存在;但是线程(指使用CreateThread创建的线程)与之不同,一旦线程返回结束,或者调用线程结束函数,则在线程创建时的堆栈会自动被内核清理掉。但是使用CONTEXT结构来管理线程的话,就需要对线程的运行机理非常的熟悉,否则很难实现对其管理。

  要想在用户态下实现对多个线程的控制(这里的控制不是指线程同步,线程同步是比较容易实现的,很多资料都有详细的讲解),最好的也是唯一的办法(用户态)就是ResumeThread和SuspendThread,因为Windows是一个多任务强占式操作系统,所以在线程调度时你很难控制内核模式下线程的情况,所以在用户态下只能使用上面的这两个函数恢复和暂停线程。上面说到线程有用户态和内核态的区分,所以当使用SuspendThread函数暂停线程时,仅仅暂停了用户态线程;也即用户态线程暂停了,在内核态它还是活跃的;但这足够了,最起码我们可以保证我们在用户态下的程序能够按照我们的想法运行了,至于内核态如何,那就是OS的事情了。

  线程包括:

  一组代码CPU状态的寄存器值;

  两个栈,用户态栈和内核态栈;

  TLS(Thread Local Storage),私有存储区域;

  线程唯一标识符,线程ID;

  线程自己的运行环境;

虚拟内存:

  这个概念等同于Unix下的swap(交换分区),针对该问题的描述,我们先以通用的说法来理解。在OS内一个程序的执行,并没有使用实际的物理地址,程序的执行通过OS与CPU来结合执行,在OS中存在一种分页机制,用于映射32位程序的地址到物理地址;若程序运行时占很大空间,可以使用swap(*nix)、PageFile.sys(Win)来进行虚拟内存映射,这些都通过分页机制来实现。

  在Windows中,使用内存管理器(Memory Manager)来实现内存映射,同时也起到保护的作用。这种保护、映射机制使得一个进程不会闯入另一个进程,也不会修改内核的数据。

  要通俗的理解的话,可以把虚拟内存机制考虑为用户态调试时可见的内存地址,但并非真实物理内存地址,然后通过Memory Manager进行内存映射。

/*++
  Virtual Memory Layout on x86 is:
         +------------------------------------+
    00000000 |                  |
         |                  |
         |                  |
         | User Mode Addresses        |
         |                  |
         |  All pages within this range   |
         |  are potentially accessible while |
         |  the CPU is in USER mode.     |
         |                  |
         |                  |
         +------------------------------------+
    7ffff000 | 64k No Access Area         |
         +------------------------------------+
    80000000 |                  |
         | NTLDR loads the kernel, HAL and  |
         | boot drivers here. The kernel   |
         | then relocates the drivers to the |
         | system PTE area.          |
         |                  |
         | Kernel mode access only.      |
         |                  |
         | When possible, the PFN database & |
         | initial non paged pool is built  |

自学PHP网专注网站建设学习,PHP程序学习,平面设计学习,以及操作系统学习

京ICP备14009008号-1@版权所有www.zixuephp.com

网站声明:本站所有视频,教程都由网友上传,站长收集和分享给大家学习使用,如由牵扯版权问题请联系站长邮箱904561283@qq.com

添加评论