真正理解微软Windows程序运行机制——什么是句柄

这篇具有很好参考价值的文章主要介绍了真正理解微软Windows程序运行机制——什么是句柄。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

windows程序句柄,Visual Studio技术,windows,microsoft,c++,visual studio,Powered by 金山文档

我是荔园微风,作为一名在IT界整整25年的老兵,今天说说Windows程序的运行机制。经常被问到MFC到底是一个什么技术,为了解释这个我之前还写过帖子,但是很多人还是不理解。其实这没什么,我在学生时代也被这个问题困绕过。而且那个时间学习资料没有那么丰富,网上也没有什么资料,周围也没有懂的人,那个时候理解MFC更困难。甚至在我看来,理解这个比理解人工神经网络更难。

我认为造成这种现象的根本原因就是没有搞清楚Windows程序的运行机制,因为不理解Windows程序的运行机制,所以给理解MFC带来了很大的困难。我决定带所有微软开发技术的初学者一起攻破这个问题,但是一篇文章肯定是讲不清楚的,我们要分好几章来说。需要你有足够的耐心,一起来吧。我们这次先来搞清楚什么是Windows程序的句柄。

句柄?难道是一个长长勺子?这个名字让很多人产生了很大的误解。

很多初学者或编程新手在编写C程序的时候,经常会调用各种库函数来辅助完成某些功能,比如大家使用最多的C库函数就是printf()和scanf(),这些库函数是由你所使用的编译器开发者提供的。而在Windows平台下,也有类似的函数可供调用,不同的是,这些函数是由Windows操作系统本身提供的。Windows操作系统提供了各种各样的函数,数量巨大,以方便我们开发 Windows应用程序。这些函数是Windows操作系统提供给应用程序编程的接口,简称API函数。我们在编写Windows程序时所说的API函数,就是指系统提供的函数。

前面说,这些函数数量巨大,有多少呢?Windows操作系统整整提供了1000多种API函数作为开发人员日常开发用!这......考验我们的记忆力?要全部记住这些函数调用的语法?我们做不到啊。那么我们该怎么办呢?如何才能更好地去使用这些函数呢?微软提供的API函数大多是有意义的单词的组合,每个单词的首字母大写,比如CreateWindow用来为程序创建一个窗口,ShowWindow用于显示窗口,LoadIcon用于加载图标,SendMessage用于发送消息。我们就按这种规律去识别函数的用途。

微软技术中总是提到一个概念: Win32 SDK开发,那么什么是 SDK呢。SDK的全称是Software Development Kit,中文译为软件开发包。其实就是Windows 32位平台下的软件开发包,包括API函数、帮助文档以及微软提供的一些辅助开发工具。

windows程序句柄,Visual Studio技术,windows,microsoft,c++,visual studio,Powered by 金山文档

举个例子,如果我们要和一家摄像头厂商合作开发一个街区的视频监控项目,摄像头厂商会提供他们的摄像头产品,同时还会提供摄像头的SDK开发包,以让我们对摄像头进行编程操作,比如移动摄像头的位置、调取拍摄到的图像、图像生成成结构化数据再传送等功能。这个开发包通常会包含摄像头的API函数库、帮助文档、使用手册、辅助工具等资源。

本文作为我们攻克MFC概念的第一篇重要文章,我们必须先攻克句柄这个小高地,不然后面的理解会很困难。下面我们就对这个高地发起进攻!

窗口是Windows应用程序中最重要的元素,一个Windows应用程序至少要有一个窗口,称为主窗口。窗口是屏幕上的一块矩形区域,是Windows应用程序与用户进行交互的接口。利用窗口,可以接收用户的输入和显示输出。一个应用程序窗口通常包含标题栏、菜单栏、左上角菜单、最小化、最大化、边框、滚动条。窗口可以分为客户区和非客户区,客户区是窗口的一部分,应用程序通常在客户区中显示文字或者绘制图形。标题栏、菜单栏、左上角菜单、最小化和最大化、边框统称为窗口的非客户区,由Windows系统来管理,而应用程序则主要管理客户区的外观及操作,换句话说,我们编程只能管到这个客户区,其他我们管不到,因为这是操作系统来干这个事的。

窗口可以有一个父窗口,有父窗口的窗口称为子窗口。另外,对话框和消息框也是一种窗口。在对话框上通常还包含许多子窗口,这些子窗口的形式有按钮、单选按钮、复选框、组框、文本编辑框等。我们再深入认识一下窗口,其实在启动Windows系统后,看到的桌面也是一个窗口,称为桌面窗口,它由Windows系统创建和管理。

windows程序句柄,Visual Studio技术,windows,microsoft,c++,visual studio,Powered by 金山文档

为什么上面我要弄一个WIN95的图,因为越是这种旧的操作系统越能看到微软窗口最初设计的本来样子。现在的系统的窗口做的都太花哨了,反而容易让人误解,看不出窗口的感觉。

好了,重点来了。什么是句柄?

在Windows应用程序中,窗口是通过窗口句柄(HWND)来标识的。我们要对某个窗口进行操作,首先就要得到这个窗口的句柄。句柄(HANDLE)是Windows程序中一个重要的概念。在Windows程序中,有各种各样的资源(窗口、图标、光标、画刷等),系统在创建这些资源时会为它们分配内存,并返回标识这些资源的标识号,即句柄。对,你没有看错,句柄句柄不是一个有着长长柄的勺子,而是一个标识号!

下面我们把这几个概念强化一下:

句柄Handle

Handle是一个32位的无符号整数,它是一个内核对象的有效抓手。它并不指向实际的内核对象,用户模式下的程序一般情况下不可能获得一个内核对象的实际地址。Handle实际上是作为一个索引在一个表中查找对应的内核对象的实际地址。每个进程都有这样的一个表,叫句柄表。该表的第一项就是进程自己的句柄。Handle本质上就是一种用来"间接"代表一个内核对象的整数值,或者叫我们上面说的标识号。你可以在程序中使用handle来代表你想要操作的内核对象。这里的内核对象包括:事件、线程、进程、文件等。Handle仅在其所属的进程中才有意义。将一个进程拥有的handle传给另一个进程没有这个必要。

进程ID

进程ID是一个32位无符号整数,每个进程都有这样的一个ID,并且该ID在系统范围内是唯一的。系统使用该ID来唯一确定一个进程。

HINSTANCE

HINSTANCE也是一个32位无符号整数,它表示程序加载到内存中的基地址。Windows是基于虚拟内存的操作系统,所以Windows内存管理器经常在内存中来回移动对象,以此来满足各种应用程序的需要。对象一被移动地址就变化了。由于地址总是变化,所以Windows操作系统为各应用程序开辟出一个专门的内存地址,用来登记各对象在内存中的地址变化,而这地址本身是不变的。Windows内存管理器在移动对象在内存中的位置后,把对象新的地址往这里保存起来。这样我们只需记住这个句柄地址就可以间接地知道对象具体在内存中的什么位置。这个地址是在对象装载时由系统分配给的,当系统卸载时又释放给系统。

HWND是窗口相关的,你可以通过HWND找到该窗口所属进程和线程。Handle 是代表系统的内核对象,如文件句柄,线程句柄,进程句柄。系统对内核对象以链表的形式进行管理,载入到内存中的每一个内核对象都有一个线性地址,同时相对系统来说,在串列中有一个索引位置,这个索引位置就是内核对象的handle。HINSTANCE的本质是模块基地址,他仅仅在同一进程中才有意义,跨进程的HINSTANCE是没有意义。

再思考一下,那这个句柄为什么要被微软设计出来?原因何在?我总结了一下,原因如下:

适应虚拟内存

Windows是一个以虚拟内存为基础的操作系统,很多时候进程的代码和数据并不全部装入内存,进程的某一段装入内存后,还可能被换出到外存,当再次需要时,再装入内存。两次装入的地址绝大多数情况下是不一样的。也就是说,同一对象在内存中的地址会变化。那程序怎么才能准确地访问到对象呢?为了解决这个问题,Windows引入了句柄。补充一下,如果没有虚拟内存这个问题,所有的程序和内存的位置都是一一对应不会改变的,那似乎就没有发明句柄的必要了。我这里留个思考题给大家,既然这是虚拟内存造成的结果,那linux系统里有没有句柄?大家想一想。

windows程序句柄,Visual Studio技术,windows,microsoft,c++,visual studio,Powered by 金山文档

32位操作系统中,系统为每个进程在内存中分配一定的区域,用来存放各个句柄,即一个个32位无符号整型值。每个32位无符号整型值相当于一个指针,指向内存中的另一个区域QY。而QY中存放的是对象在内存中的地址。当对象在内存中的位置发生变化时,QY的值被更新,变为当前对象在内存中的地址,而在这个过程中,QY的位置以及对应句柄的值是不发生变化的。也可以表述为:有一个固定的地址(句柄),指向一个固定的位置(QY),而QY中的值可以动态地变化,它记录着当前对象在内存中的地址。

windows程序句柄,Visual Studio技术,windows,microsoft,c++,visual studio,Powered by 金山文档

这样,无论对象的位置在内存中如何变化,只要我们掌握了句柄的值,就可以找到QY,进而找到该对象。而句柄的值在程序本次运行期间是绝对不变的,操作系统是可以控制这个程序的,也就是抓住了程序的把柄。句柄是Windows中各个对象的一个唯一的、固定不变的ID,操作系统在启动后,会建立一个句柄表,程序在Windows系统上运行时会由操作系统给每个对象分配句柄,包括窗体句柄、文件句柄以及窗体上控件的句柄。Windows使用句柄来标识诸如窗口、位图、画笔等对象,并通过句柄找到这些对象。完整的链条关系如下:句柄地址(不变化)->记载着对象在内存中的地址->对象在内存中的地址(经常变化)->实际对象。

windows程序句柄,Visual Studio技术,windows,microsoft,c++,visual studio,Powered by 金山文档

在程序的运行中,如果程序某一次运行完并关闭程序,后来再次启动程序运行,那么后来这次运行中,同一对象的句柄的值和上次运行时句柄的值一般是不一样的。程序每次重新启动,系统不能保证分配给这个程序的句柄还是原来的那个句柄,而且绝大多数情况的确是不一样的。句柄是对象生成时系统指定的,属性是只读的,程序员不能修改句柄。不同的系统中,句柄的大小(字节数)是不同的,可以使用sizeof()来计算句柄的大小。

适应内存管理

句柄的设计还解决了一个问题。操作系统有定期整理内存的计划任务,如果一些内存整理过一次后,对象找不到了怎么办?所以,Windows操作系统就采用这种设计理念,即指针的指针——句柄:在进程的地址空间中设一张表,表里头专门保存一些标识号(句柄)和由这个标识号(句柄)对应一个地址,再由那个地址去引用实际的对象,这个标识号(句柄)跟那个地址在数值上没有任何规律性的联系,只是映射。

提高调用效率

程序员只能通过句柄调用系统提供的服务(即API调用),但不能任意做超越权限的事,也就是不能像使用指针那样使用句柄做其他的操作,必须通过系统封装的API去使用。Windows系统中有许多内核对象,比如打开的文件,创建的线程,程序的窗口等等。这些对象因为复杂肯定不是4个字节或者8个字节足以完全描述的,他们拥有大量的属性。为保存这样一个"对象"的状态,往往需要上百甚至上千字节的内存空间,那么怎么在程序间或程序内部的子过程(函数)之间高效的传递这些数据呢?学过C语言的人会说可以传递这些对象的首地址呀,这确实是一个办法,你传一个地址效率高还是传一个窗口的所有数据效率高?显然是地址效率高。所以句柄的使用有效的提高了效率。

增加安全性

但这样做虽然会提高效率,却带来了安全风险,因为这样做会暴露了内核对象本身,使得其他程序因为知道了首地址,可以任意修改对象内部状态,这显然是操作系统内核所不允许的。所以句柄的使用增加了安全性。句柄和指针都是地址,不同之处在于句柄所指的可以是一个很复杂的结构,并且很有可能是与系统相关的,比如说线程的句柄,它指向的就是一个类或者结构,它和系统有很密切的关系。当一个线程由于不可预料的原因终止时,系统就可以返回这个线程所占用的的资料,如CPU ,内存等。句柄中的某一些项是与系统进行交互的。由于Windows系统是一个多任务的系统,它随时都可能要分配内存,回收内存,重组内存。指针也可以指向一个复杂的结构,但是通常是用户定义的,所以必须的工作都要用户完成。

总而言之,Windows程序中并不是用物理地址来标识一个内存块、文件或任务对象。Windows API给这些对象分配确定的句柄,并将句柄返回给应用程序,然后通过句柄来进行操作。在Windows编程中会用到大量的句柄。比如HINSTANCE(实例句柄),HBITMAP(位图句柄),HDC(设备表述句柄),HICON(图标句柄)等。

好了,看到这里,马上去看我的前一篇文章,你就能看明白句柄的意思了以及是怎么在程序上使用的。可点击下面链接。

帮你快速理解什么是MFC(Windows环境下)

各位小伙伴,这次我们就说到这里。下次我们再深入研究windows MFC和windows程序运行机制,相信你一定能喜欢上windows MFC。请关注我的这个系列的文章。

作者简介:荔园微风,1981年生,高级工程师,浙大工学硕士,软件工程项目主管,做过程序员、软件设计师、系统架构师,早期的Windows程序员,Visual Studio忠实用户,C/C++使用者,是一位在计算机界学习、拼搏、奋斗了25年的老将,经历了UNIX时代、桌面WIN32时代、Web应用时代、云计算时代、手机安卓时代、大数据时代、ICT时代、AI深度学习时代、智能机器时代,我不知道未来还会有什么时代,只记得这一路走来,充满着艰辛与收获,愿同大家一起走下去,充满希望的走下去。文章来源地址https://www.toymoban.com/news/detail-762292.html

到了这里,关于真正理解微软Windows程序运行机制——什么是句柄的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 怎么才能真正理解服务器是什么?

    构成互联网世界的基本节点是一个又一个的计算机和网络设备。 服务器是提供特定服务的计算机,你平时用的计算机叫做终端设备。他们在机器上的本质是一样的,但因为承担不同的角色,所以有一些区别: 0、归属与成本 服务器:属于提供服务者,一般是公司等团体组织需

    2024年02月09日
    浏览(25)
  • 微软MFC技术运行机制

    我是荔园微风,作为一名在IT界整整25年的老兵,今天总结一下微软MFC技术运行机制。 很多初学者误以为VC++开发必须使用MFC,其实不一定的。MFC的使用只能是提高程序在某些情况下的开发效率,而不能替代整个Win32程序设计。我认为我们有必要再来好好讲讲MFC的本质、MFC中的

    2024年02月08日
    浏览(32)
  • 深入理解Windows操作系统机制(二)

    我是荔园微风,作为一名在IT界整整25年的老兵,今天我们来重新审视一下Windows这个我们熟悉的不能再熟悉的系统。 我们每天都在用Windows操作系统,但是其实我们每天直接在打交道的并不是Windows操作系统的内核,而是Windows操作系统的人机交互界面,这个界面其实只是Window

    2024年02月17日
    浏览(39)
  • “深入探索JVM内部机制:理解Java虚拟机的运行原理“

    标题:深入探索JVM内部机制:理解Java虚拟机的运行原理 摘要:本篇博客将深入探索Java虚拟机(JVM)的内部机制,帮助读者理解JVM的运行原理。我们将介绍JVM的组成结构,包括类加载器、运行时数据区域和执行引擎,并通过示例代码解释这些概念的具体应用。 正文: 一、J

    2024年02月11日
    浏览(35)
  • MATLAB中的函数句柄 理解

    https://zhuanlan.zhihu.com/p/266263265 https://blog.csdn.net/kevinhg/article/details/8861774 函数句柄也是MATLAB中的一种常见的数据类型,它的地位类似于其它计算机语言里的函数对象(Javascript,Python),函数指针(C++),或者函数引用(Perl)。 它的作用是将一个函数封装成一个变量,使其能够像其它变量

    2024年02月03日
    浏览(24)
  • 微软MFC程序运行的正确顺序

     我是荔园微风,作为一名在IT界整整25年的老兵,今天来看一下微软MFC程序运行的正确顺序。这真的只是一个小众话题。但是对理解MFC很重要。 很多人写了一堆MFC程序,却不知道MFC程序是怎么运行顺序的。我们就来看一看这个问题。 我在之前的帖子中多次提到,main()函数也

    2024年02月13日
    浏览(20)
  • Android HAL机制的深入理解及在Linux上移植和运行的一个好玩的HAL小例子

    PS:要转载请注明出处,本人版权所有。 PS: 这个只是基于《我自己》的理解, 如果和你的原则及想法相冲突,请谅解,勿喷。 环境说明   Ubuntu 18.04.x   近一年来,虽然还是做的是AIOT相关的事情,但是某些事情却发生了一些变化。随着个人的阅历提升,现在的AI在边缘端

    2023年04月08日
    浏览(30)
  • 4.小程序的运行机制

    把小程序的代码包下载到本地 解析app.json全局配置文件 执行app.js小程序入口文件,调用App()创建小程序的实例 渲染小程序首页 小程序启动完成 加载解析页面的.json配置文件 加载页面.wxml模板和.scss样式 执行页面的.ts文件,调用Page()创建页面实例 页面渲染完成

    2024年02月12日
    浏览(22)
  • 真正理解红黑树,真正的(Linux内核里大量用到的数据结构

    作为一种数据结构,红黑树可谓不算朴素,因为各种宣传让它过于神秘,网上搜罗了一大堆的关于红黑树的文章,不外乎千篇一律,介绍概念,分析性能,贴上代码,然后给上罪恶的一句话,它最坏情况怎么怎么地... 我们想,一棵二叉树怎么就是最坏情况,那就是它退化为一

    2024年02月16日
    浏览(25)
  • 微信小程序的【运行机制】解读

    前面我们有章节给大家讲到了,微信小程序的生命周期钩子函数,那么大家知道,这些不同的生命周期函数,是在什么样的操作运行模式下触发的吗?本章节就给大家整理了有关于 微信小程序 的操作运行机制,以便于对后面微信小程序的开发理解。 微信小程序从启动到最终

    2024年02月06日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包