图片 2

Windows编制程序的实质,Windows程序设计

既然Windows API编程是与Windows操作系统进行交互,所以就必须对Windows操作系统如何运行应用程序的原理搞清楚。

    • CPU保护模式与Windows系统
      • 1
        Windows多任务
      • 2
        虚拟内存
      • 3
        处理器的特权级别
    • 内核对象
      • 1
        内核对象有什么用
      • 2
        对象句柄
      • 3
        使用计数

1、保护模式

1 CPU保护模式与Windows系统

80386的CPU有3种工作模式:实模式、保护模式、和虚拟86模式。其中实模式和虚拟86模式是为了兼容8086CPU而设置的。保护模式是其主要的工作模式。Windows操作系统就运行在保护模式,而保护主要指的就是对存储器(内存和寄存器)的保护,意味着对存储器的读写是受限制的。

     操作系统是依附于cpu硬件的,所以操作系统所具备的功能也是cpu所给予的。Intel的32位CPU有两种主要的模式:实模式和保护模式。Dos操作系统就是运行在实模式下,而现代的操作系统都是充分利用了保护模式,从而使系统大大的安全稳定了很多。现代计算机都是用的冯诺依曼体系,其核心就是内存。所以CPU内部有寄存器,外部有内存,所以所谓的实模式和保护模式其本质就是对内存的访问形式不同。实模式就是对内存的直接访问,比如要在屏幕上显示一个数字就直接往显存中写就可以了,dos下编程就是这样的。但这有一个最大的问题就是不安全,任何程序可以随意访问内存,很容易就和操作系统的地址冲突,所以玩过dos的人都知道电脑是很容易死机的。为了解决这个问题,Intel在386以后的CPU都提供了保护模式。这种模式最重要的一个应用就是虚拟内存地址,大家都知道32位的CPU可以寻址的范围是4GB,在虚拟内存中给每一个进程都分配了4GB的虚拟地址。如果同时运行10个进程就要有10个4GB的虚拟内存,那问题来了,哪有这么多的内存呢?呵呵,所以这是虚拟内存嘛,不是真正的物理内存。只是面对进程,让程序员可以使用的内存地址,比如 int * p=new int 这句话是向电脑要一个4字节的内存,地址存在p里面,要是在实模式下p里面就是真正的物理地址,但是在保护模式下,p里面存的只是一个虚拟地址,至于真正的物理地址是多少是不允许程序员知道的,当windows拿到p后会把p里面的虚拟地址映射到一个物理地址中去的,而这一个过程是黑箱操作,普通的应用程序是不允许知道的。

1.1 Windows多任务

80386在两个方面对多任务系统提供了支持:一是在硬件上为任务的切换提供良好条件,二是实现了多任务隔离。

在同一时间系统中会有多个活动的进程。每个进程都被给予它自己的私有地址空间。进程内的线程运行时,该线程仅仅能够访问属于它的进程内存空间。在不同的进程中可以有存放在相同地址的数据结构,但它们彼此没有关联,因为它们在各自的地址空间中。

这里所说的进程就是正在运行的应用程序的实例。而占用CPU时间片执行指令的是线程。

2、内核空间和用户空间:

1.2 虚拟内存

在保护模式下,CPU寻址范围是0x00000000~0xFFFFFFFF(232,
4GB)。Windows会为每个进程分配4GB的地址空间,也就是虚拟内存。主要依靠CPU的支持,可以将磁盘空间当作内存空间来使用。在磁盘上应用于这一机制的文件称为页文件(paging
file)。

在大多数的操作系统上,Windows将些空间的一半(4GB的前半部分,
0x00000000~0x7FFFFFFF)留给进程作为私有存储。另一半(0x80000000~0xFFFFFFFF)来存储操作系统内部的数据。

图片 1

    好了,现在知道在保护模式下编写程序访问的是4GB的虚拟内存,但是这4GB空间也不是全部给应用程序用的,操作系统也要使用,所以Windows规定把4GB空间分成两半,低2GB(0—0x7fffffff)空间用户可以使用,而高2GB空间(0x80000000—0xffffffff)用户不能使用,留给操作系统。所以这就有了用户空间和内核空间的区别。而这个规定其实也是用了CPU的特权级的功能:内核空间是0环,用户空间在3环,所以这就在CPU级别把内核和用户程序分割开了,目的就是确保用户程序不能骚扰内核,从而保证系统稳定。

1.3 处理器的特权级别

处理器定义了4种(0~3)特权级别。Windows使用了0和3两个特权级别,对应于内核模式和用户模式。用户程序在用户模式下运行,系统程序在内核模式下运行。

图片 2

当应用程序调用一个系统函数的时候,用户的应用程序会从用户模式切换到内核模式去执行。虚拟内存中的每一页的页属性都有访问模式的标识,标识哪一个模式下的代码才有权限去访问该页,这样就很好的区分了不同模式下的访问权限。

一般来说,研究WDM(Windows Driver
Model)设备驱动的书讨论的是内核模式下的Windows程序设计,而SDK程序设计主要指的是用户模式下的程序设计。

3、内核对象:

2 内核对象

内核对象是系统提供的用户模式下与内核模式下代码进行交互的基本接口。经常需要创建、撕开和操作内核对象。

  
但现在问题又来了,内核空间用户不能访问,那么操作系统的各种功能我们怎么调用呢?比如往屏幕上画一条线,在实模式下很简单,就是在显存里面写一排01010101就可以了,但是在实模式下我们只能访问2GB用户空间,显存在哪里都不知道,这怎么写啊?很容易想到的就是操作系统帮我们找显存的位置,我们只要调用操作系统的相关函数就可以了。但是操作系统在高2GB的内核空间中,我们还是不能直接使用。现在操作系统既要给我们用,又不能让我们直接用,那怎么办呢,微软的工程师想出的一个办法就是给我们一个编号,也就是句柄(HANDLE),让我们要用内核什么功能就用句柄来用,这样就不必让我们知道具体的内核地址了。从而内核对象也就自然产生,Windows对硬件的所有操作都做成一个一个内核对象,我们要用的时候就申请这个对象,然后Windows给我们一个句柄,Windows内部计数器加1,我们不用了就关闭句柄,Windows内部计数器减1,当计数器为0的时候,Windows知道这个内核对象已经不用了,所以从真实物理内存中销毁。对于我们应用程序员来说,我们要做的事情就是申请内核对象,拿到句柄,操作句柄,销毁句柄。而这个流程也就是和Windows交互的流程,也就是所谓Windows编程的本质。

2.1 内核对象有什么用

为了管理应用程序,系统有必要维护一些不允许应用程序直接访问的数据。一个内核对象是一块内核分配的内存,它只能被运行在内核模式下的代码访问。内核对象记录的数据在整个系统中只有一份,所以它们也称为系统资源。

对于每一个内核对象,Windows都提供了在其上操作的API函数,这些API函数使应用程序有机会读或者写系统数据,但这一切都是在系统监视下进行的。

内核对象与普通的数据结构间最大的区别就是其内部数据结构是隐藏的,必须调用一个对象服务才能从些对象中得到数据,或者修改数据。因此,内核对象可以完成下面4个任务:

  • 为系统资源提供可识别的名字。
  • 在进程之间共享资源和数据。
  • 保护资源不会被未经认可的代码访问。
  • 跟踪对象的引用情况。使得系统知道什么时候一个对象不再被使用了,
    以回收资源。

2.2 对象句柄

内核对象的数据结构仅能从内核模式访问,应用程序必须使用API函数才能访问内核对象。调用函数创建内核对象时,函数会返回标识此内核对象的句柄。可以将句柄认为是一个能被进程中所有线程使用的一个不透明的值,许多API函数需要使用它们作为参数,以便系统知道要操作哪一个内核对象。

一般来讲,句柄是进程相关的。但使用DuplicateHandle函数可以复制进程句柄,实现多个进程共享一个内核对象。

2.3 使用计数

内核对象是进程内的资源,使用计数属性指明进程对特定内核对象的引用次数,当系统发现引用次数是0时,它就会关闭资源。

发表评论

电子邮件地址不会被公开。 必填项已用*标注