Win32 基本程序设计原理总结

news2024/11/15 22:48:16

目录

1. Windows系统 基本原理

2. 需要什么函数库(.LIB)

2.1 C Runtimes:

2.2 Windows API

3. 需要什么头文件(.H)

4. Windows 程序运行的本质

5. 窗口类的注册与窗口的诞生

6.消息

6.1 消息分类:

7. 消息队列

8. 消息循环

9. 窗口的生命中枢:窗口函数(窗口过程)

10. 对话框窗口的运作

11. 资源描述文件(.RC)

12. Windows 程序的生与死

13. 问答


参考:侯杰的书,感谢JJ深入浅出的介绍! 
第1章 Win32 基本程序观念 | 深入浅出MFC (gitbooks.io)

1. Windows系统 基本原理

    Windows 操作系统本身,主要是 Windows 三大模块 GDI32.DLL 和 USER32.DLL 和 KERNEL32.DLL提供的。    
   下图是Windows SDK程序(Win32)的开发流程图:

我们基于Windows编程,肯定不是从零开始搭建,是基于Windows函数库,以及微软封装的其他功能函数库开发的。

2. 需要什么函数库(.LIB)

编译器驱动程序读取源程序文件.c,并把它翻译成一个可执行目标文件exe。这个翻译过程分为四个阶段:预处理(Preprocessing)、编译(Compilation)、汇编(Assembly)、链接(Linking)。执行这四个阶段的程序(预处理器、编译器、汇编器、和链接器)一起构成了编译系统。
参考: 程序详细编译过程(预处理、编译、汇编、链接) - 知乎 (zhihu.com)

在链接时期,链接器仍需先为调用者(应用程序本身)准备一些适当的资讯,才能够在运行时顺利「跳」到 DLL 执行。
Windows支持静态链接库lib(链接时期),和动态链接库dll(运行时期)。

文件名为 .dll 者是动态链接函数库(DLL,Dynamic Link Library),事实上.exe、.dll、.fon、.mod、.drv、.ocx 都是所谓的动态链接函数库。

Windows 程序调用的函数可分为 C Runtimes 以及 Windows API 两大部分。

2.1 C Runtimes:

  • LIBC.LIB - 这是C Runtime 函数库的静态链接版本。

  • MSVCRT.LIB - 这是C Runtime 函数库动态链接版本(MSVCRT40.DLL)的 import 函数库。如果链接此一函数库,你的程序执行时必须有 MSVCRT40.DLL 在场。

2.2 Windows API

  • Windows 的三大模块所对应的 import 函数库分别为 GDI32.LIB 和 USER32.LIB 和 KERNEL32.LIB,动态库对应的是 GDI32.DLL 和 USER32.DLL 和 KERNEL32.DLL。

3. 需要什么头文件(.H)

所有Windows程序都必须含入WINDOWS.H,不过,WINDOWS.H 只照顾三大模块所提供的API 函数。如果你用到其它 system DLLs,就得含入对应的头文件。

4. Windows 程序运行的本质

Windows 程序运行的本质是以消息为基础,以事件为驱动。Windows程序的事件驱动特性,包括消息的产生、获得、分派、判断、处理

Windows 程序的进行系依靠外部发生的事件来驱动。换句话说,程序不断等待(利用一个 while 循环),等待任何可能的输入,然后做判断,然后再做适当的处理。上述的「输入」是由操作系统捕捉到之后,以消息形式(一种数据结构)进入程序之中。操作系统如何捕捉外围设备(如键盘和鼠标)所发生的事件呢?噢,USER 模块掌管各个外围的驱动程序,它们各有侦测循环。

如果把应用程序获得的各种「输入」分类,可以分为由硬件装置所产生的消息(如鼠标移动或键盘被按下),放在系统队列(system queue)中,以及由 Windows 系统或其它Windows 程序传送过来的消息,放在程序队列(application queue)中。以应用程序的眼光来看,消息就是消息,来自哪里或放在哪里其实并没有太大区别,反正程序调用GetMessage API就取得一个消息,程序的生命靠它来推动。所有的GUI系统,包括UNIX的X Window 以及OS/2的Presentation Manager,都像这样,是以消息为基础的事件驱动系统。 

Windows 程序的本体与操作系统之间的关系图:

WinMain 则是Windows 程序的进入点:

nt CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine,     int nCmdShow)
{
...
} // 在 Win32 中 CALLBACK 被定义为 __stdcall,是一种函数调用习惯,关系到参数挤压到堆栈的次序,以及处理堆栈的责任归属。其它的函数调用习惯还有_pascal和_cdecl


当Windows的「外壳」(shell,例如 Windows 3.1的程序管理员或Windows 95的文件总管)侦测到使用者意欲执行一个 Windows 程序,于是调用加载器把该程序加载,然后调用C startup code,后者再调用WinMain,开始执进程序。

5. 窗口类的注册与窗口的诞生

一开始,Windows 程序必须做些初始化工作,为的是产生应用程序的工作舞台:窗口。这没有什么困难,因为API函数CreateWindow完全包办了整个巨大的工程。但是窗口产生之前,其属性必须先设定好。所谓属性包括窗口的「外貌」和「行为」,一个窗口的边框、颜色、标题、位置等等就是其外貌,而窗口接收消息后的反应就是其行为(具体地说就是指窗口函数本身)。程序必须在产生窗口之前先利用 API 函数 RegisterClass设定属性(我们称此动作为注册窗口类)。RegisterClass 需要一个大型数据结构WNDCLASS 做为参数,CreateWindow 则另需要11个参数。

RegisterClass与CreateWindow关系图

可以清楚看出一个窗口类牵扯的范围多么广泛,其中wc.lpfnWndProc所指定的函数就是窗口的行为中枢,也就是所谓的窗口函数。注意,CreateWindow只产生窗口,并不显示窗口,所以稍后我们必须再利用 ShowWindow 将之显示在屏幕上。又,我们希望先传送个WM_PAINT给窗口,以驱动窗口的绘图动作,所以调用UpdateWindow

6.消息

消息,就是指Windows发出的一个通知,告诉应用程序某个事情发生了。例如,单击鼠标、改变窗口尺寸、按下键盘上的一个键都会使Windows发送一个消息给应用程序,它被定义为:

typedef struct {
HWND hwnd; //窗口句柄, 发生在哪个窗口上
UINT message; //消息标识号 ( WM_MOUSEMOVE, WM_LBUTTONDOWN, ... )
WPARAM wParam; //消息参数1
LPARAM lParam; //消息参数2
DWORD time;
POINT pt;
} MSG, *PMSG;

其中的成员变量 message 是 WM_SIZE 、 WM_COMMAND 、 WM_QUIT 等等消息标识。hwnd 中是这个消息所在的窗口句柄。time和pt由系统生成这个消息时填充。
一个消息结构体包含了该事件 所有完备信息,当应用程序收到该消息时,就可以做出相应处理了。

6.1 消息分类:

  •  队列消息和非队列消息

从消息的发送途径上看,消息分两种:队列消息和非队列消息。队列消息送到系统消息队列,然后到线程消息队列;非队列消息直接送给目的窗口过程。
除了键盘、鼠标消息以外,队列消息还有WM_PAINT、WM_TIMER和WM_QUIT。这些队列消息以外的绝大多数消息是非队列消息。

  •  系统消息和应用程序消息

从消息的来源来看,可以分为:系统定义的消息和应用程序定义的消息。
系统消息ID的范围是从0到WM_USER-1,或0X80000到0XBFFFF;应用程序消息从WM_USER(0X0400)到0X7FFF,或0XC000到0XFFFF;WM_USER到0X7FFF范围的消息
由应用程序自己使用;0XC000到0XFFFF范围的消息用来和其他应用程序通信,为了ID的唯一性,使用::RegisterWindowMessage来得到该范围的消息ID。

  •  窗口消息,命令消息,控件通知消息,根据处理过程的不同,可以分为三类:窗口消息,命令消息,控件通知消息。

(1) 窗口消息
一般以WM_开头,如WM_CREATE, WM_SIZE, WM_MOUSEMOVE等标准的Windows消息, 用于窗口相关的事件通知,窗口消息将由系统分配到该窗口的窗口过程处理。
(2) 命令消息 (WM_COMMAND)
一种特殊的窗口消息,它从一个窗口发送到另一个窗口以处理来自用户的请求,通常是从子窗口发送到父窗口,例如,点击按钮时,按钮的父窗口会收到WM_COMMAND消息,用以通知父窗口按钮被点击,经测试:子窗口向父窗口发送WM_COMMAND消息,或者称为父窗口会收到WM_COMMAND消息,操作系统并不是通过将WM_COMMAND消息放入到父窗口的消息队列中去,而是直接调用了父窗口的窗口过程,以 WM_COMMAND 为消息标识参数(UINT uMsg),实现这个功能的API函数正是: LRESULT DispatchMessage(const MSG *lpmsg);
(3) 控件通知消息
WM_NOTIFY消息,当用户与控件交互(Edit, Button...)时,通知消息会从控件窗口发送到父窗口,这种消息的目的不是为了处理用户命令,而是为了让父窗口能够适时的改变控件。

7. 消息队列

一个进程至少拥有一个线程,称为主线程,如果一个线程创建了窗口,拥有GUI资源,那么也称该线程为GUI线程,否则就为工作线程。窗口是由线程创建的,创建窗口的线程就拥有该窗口。这种线程拥有关系的概念对窗口有重要的意义:建立窗口的线程必须是为窗口处理所有消息的线程。

在Windows操作系统中,不是每一个线程都有自己的消息队列。只有那些创建了窗口的线程或者明确调用了PeekMessage或GetMessage函数的线程才会有消息队列。这些消息队列用于存储各种来自系统、应用程序或其他线程的消息,以便线程能够按照一定的顺序处理它们。如果一个线程没有消息队列,那么它就无法接收和处理用户输入、窗口更新等消息,这在大多数情况下是不可取的。因此,通常我们会看到至少有一个拥有消息队列的线程在运行,以处理各种系统消息和用户交互。但是,也有一些线程是不需要消息队列的,比如那些只负责后台计算或者数据处理的线程。这些线程通常会避免创建消息队列,以减少资源消耗和提高效率。总的来说,是否为一个线程创建消息队列,取决于这个线程的具体任务和需求。

另外,系统还维护一个全局的系统消息队列,用来接受鼠标,键盘等外设触发的消息。并根据消息的窗口句柄,窗口所属的线程,不断移除系统队列的消息,放到对应的线程队列中,线程内又有一个小希循环,不断的获取消息,并由DispatchMessage 分派到对应窗口的窗口过程中处理。每个消息都应该得到妥善的处理,如果应用程序不处理的消息,应该交由系统默认的窗口过程DefWindowProc处理。

每个线程,如果它至少建立了一个窗口,都由系统(一般是在线程调用GetMessage或者PeekMessage时)对它分配一个消息队列。这个队列用于窗口消息的派送(dispatch)。为了使窗口接收这些消息,线程必须有它自己的消息循环。

Windows维护一个系统消息队列(System message queue),每个GUI线程有一个线程消息队列(Thread message queue)。鼠标、键盘事件由鼠标或键盘驱动程序转换成输入消息并把消息放进系统消息队列,例如WM_MOUSEMOVE、WM_LBUTTONUP、WM_KEYDOWN、WM_CHAR等等。Windows每次从系统消息队列移走一个消息,确定它是送给哪个窗口的和这个窗口是由哪个线程创建的,然后,把它放进创建窗口的线程消息队列。线程消息队列接收送给该线程所创建窗口的消息。线程从消息队列取出消息,通过Windows把它送给适当的窗口过程来处理。

8. 消息循环

窗口初始化工作完成后,WinMain 进入所谓的消息循环:

BOOL bRet;

while( (bRet = GetMessage( &msg, hWnd, 0, 0 )) != 0)  // 不断的尝试到消息队列获取消息
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg);   // 转换键盘消息
        DispatchMessage(&msg);    // 经过USER模块的协助,把消息交到窗口函数
    }
}

windows 消息处理机制:
首先 Windows OS 把来自硬件 ( 鼠标 ,键盘等消息 ) 和来自应用程序的消息放到一个 OS 系统消息队列中去 ,Windows 系统会不断的处理系统消息队列内的消息,根据消息中附带的窗口句柄,把消息放到对应的应用程序的线程消息队列中。然后应用程序的消息循环每次取出一条消息发送到指定窗口过程 , 直到程序退出。这个循环就是靠消息环实现的 GetMessage() 从线程消息中取出一条消息 , 而 DispatchMessage则把取出的消息发送到目的窗口。如果收到 WM_QIUT 消息则结束循环,发送 PostQuitMessage(0),处理WM_DESTROY 销毁窗口。

9. 窗口的生命中枢:窗口函数(窗口过程)

 窗口过程就是一个拥有有固定签名的 C函数回调,具体格式如下:

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

窗口函数通常利用switch/case方式判断消息种类,以决定处置方式。由于它是被Windows系统所调用的(我们并没有在应用程序任何地方调用此函数),所以这是一种call back函数,意思是指「在你的程序中,被 Windows 系统调用」的函数。这些函数虽然由你设计,但是永远不会也不该被你调用,它们是为 Windows 系统准备的。程序进行过程中,消息由输入装置,经由消息循环的抓取,源源传送给窗口并进而送到窗口函数去。不论什么消息,都必须被处理,所以switch/case 指令中的default: 处必须调用DefWindowProc,这是 Windows 内部预设的消息处理函数。

10. 对话框窗口的运作

Windows 的对话框依其与父窗口的关系,分为两类:

1.「令其父窗口除能,直到对话框结束」,这种称为modal 对话框。

2.「父窗口与对话框共同运行」,这种称为modeless 对话框。

为了做出一个对话框,程序员必须准备两样东西:

1. 对话框模板(dialog template)。这是在 RC 文件中定义的一个对话框外貌,以各种方式决定对话框的大小、字形、内部有哪些控制组件、各在什么位置...等等。

2. 对话框函数(dialog procedure)。其类型非常类似窗口函数,但是它通常只处理WM_INITDIALOG和WM_COMMAND两个消息。对话框中的各个控制组件也都是小小窗口,各有自己的窗口函数,它们以消息与其管理者(父窗口,也就是对话框)沟通。而所有的控制组件传来的消息都是 WM_COMMAND,再由其参数分辨哪一种控制组件以及哪一种通告(notification)。

Modal 对话框的启动与结束,靠的是DialogBox 和EndDialog 两个API 函数。

对话框的诞生、运作、结束:

对话框处理过消息之后,应该传回TRUE;如果未处理消息,则应该传回FALSE。这是因为你的对话框函数之上层还有一个系统提供的预设对话框函数。如果你传回FALSE,该预设对话框函数就会接手处理。

11. 资源描述文件(.RC)

RC文件是一个以文字描述资源的地方。常用的资源分别是 ICON、CURSOR、 BITMAP、FONT、DIALOG、MENU、ACCELERATOR、STRING、VERSIONINFO。这些文字描述需经过RC编译器,才产生可使用的二进位代码。

12. Windows 程序的生与死

我们已经了解Windows程序的架构以及它与Windows系统之间的关系。对Windows 消息种类以及发生时机的透彻了解,正是程序设计的关键。现在我以窗口的诞生和死亡,说明消息的发生与传递,以及应用程序的兴起与结束。

窗口的生命周期:

1. 程序初始化过程中调用CreateWindow,为程序建立了一个窗口,做为程序的屏幕舞台。CreateWindow 产生窗口之后会送出WM_CREATE直接给窗口函数,后者于是可以在此时机做些初始化动作(例如配置内存、开文件、读初始数据...)。

2. 程序活着的过程中,不断以GetMessage从消息贮列中抓取消息。如果这个消息是WM_QUIT,GetMessage 会传回0而结束while循环,进而结束整个程序。

3. DispatchMessage 通过Windows USER 模块的协助与监督,把消息分派至窗口函数。消息将在该处被判别并处理。

4. 程序不断进行2.和3.的动作。

5. 当使用者按下系统菜单中的Close命令项,系统送出WM_CLOSE。通常程序的窗口函数不栏截此消息,于是DefWindowProc 处理它。

6. DefWindowProc收到WM_CLOSE后 ,调用DestroyWindow 把窗口清除 。DestroyWindow 本身又会送出WM_DESTROY。

7. 程序对WM_DESTROY的标准反应是调用PostQuitMessage。

8. PostQuitMessage 没什么其它动作,就只送出WM_QUIT 消息,准备让消息循环中的GetMessage 取得,如步骤2,结束消息循环。

因为操作系统与应用程序职责不同,二者是互相合作的关系,所以必需各做各的份内事,并互以消息通知对方。

  • GetMessage 会过门不入,于是操作系统再去照顾其它人。

  • PeekMessage 会取回控制权,使程序得以执行一段时间。于是上述消息循环进入OnIdle 函数中。

13. 问答

1 每个窗体是一个 UI thread ,还是只有一个 UI thread?
答: 所有的窗体都用这一个 UI thread。当然可以有两个UI 线程,如果除了主线程外,另一个线程也创建了窗口,并调用了GetMessage或者PeekMessage时,系统也会给它创建消息队列。具体看微软文档。

2 Message queue: 每个窗体都有一个 message queue ,还是共用一个 message queue? 
答:同一个线程的窗体共用一个消息队列。

3 message 处理:是同步还是异步。是每次处理一个消息等这个消息处理完后再处理另一个消息还是每次取一个不等这个消息处理完就处理下一个,也就是 dispatchmessage 什么时候返回?
答:要等这个窗口过程处理函数处理完这个消息以后才返回,否则会造成消息处理的混乱

4 Windows 如何知道消息应该送到哪一个线程,
答:这里我们要分为两种情况 , 消息是不是队列消息 , 比如在一个窗体空白处点击左键 , 首先 OS 会根据当前的context 来生成 MSG , MSG 中会包括要发送到的窗口的 Handle, 这就是一个队列消息 , 首先 OS 会将这个消息放到 OS 的系统消息队列中 , 而后 OS 会有专门的进程根据 MSG 中的窗口的 Handle 找到创建该窗口的线程,而后将该 MSG 送到该线程的消息队列,而后由该消息循环来处理这个消息, 最终由DispatchMessage 函数来将这个消息送到相应的窗口处理函数。
如果你在一个窗体上点击了一个 button 呢,消息的路径是怎样的呢?当你点击了一个 button 后, OS 产生三个MSG。 WM_LBUTTONDOWN和WM_LBUTTONUP,这两个消息的窗口Handle为button的handle。一个WM_command 或者 wm_notify 消息, OS 会将这个消息直接送给包含 button 的 window processdure 来处理,而不会将这个送到消息队列。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1353476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3 结合typescript 组合式函数(2)

安装axios:npm install axios 1、hooks文件夹下新建useURLLoader 在APP.VUE中使用useURLLoader 使用Dog API 2、使用对象中的属性,必须使用toRefs,否则Reactive响应失效 3、使用泛型 结果:

VS2022 Android NativeActivity 开发指南

几年前最初使用VS时,记得是有Android NativeActivity的,今天更新到了2022最新版,发现找不到这个创建选项。 然后确保安装了C 跨平台开发工具后,开始排查原因。 Visual Studio 2022 中没有“本机活动应用程序” - android - SO中…

vue中$nextTick作用和实例

为什么要使用nextTick? vue中DOM更新是异步执行,相当于我们在修改数据的时候,视图是不会立即更新的,会先把新的数据攒一赞,例如假如v-for更新这三个数据item1和item2和item3,按照vue的特性dom更新的特性会…

SpingBoot的项目实战--模拟电商【4.订单及订单详情的生成】

🥳🥳Welcome Huihuis Code World ! !🥳🥳 接下来看看由辉辉所写的关于SpringBoot电商项目的相关操作吧 目录 🥳🥳Welcome Huihuis Code World ! !🥳🥳 一.功能需求 二.代码编写 …

CSS与JavaScript的简单认识

CSS:是一门语言,用于控制网页表现,让页面更好看的。 CSS(Cascading Style Sheet):层叠样式表 CSS与html结合的三种方式: 1、内部样式:用style标签,在标签内部定义CSS样式…

java仓库管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web仓库管理系统是一套完善的java web信息管理系统,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发,数据库为Mysql5.0&…

Python控制程控电源(USB)

文章目录 前言一、环境搭建1.软件安装2.硬件安装二、设置程控电源连接方式三、Python代码四、验证结果五、pyd文件前言 随着智能电动汽车行业的持续发展,汽车电子或嵌入式设备在软硬件的测试中,都会使用程控电源供电,特别是自动化测试、压力测试场景必定使用到程控电源控制…

【Mybatis】深入学习MyBatis:CRUD操作与动态SQL实战指南

🍎个人博客:个人主页 🏆个人专栏: Mybatis ⛳️ 功不唐捐,玉汝于成 目录 前言 正文 一基本用法 1 CRUD操作 1. 增加(Create) 2. 查询(Read) 3. 更新&#x…

test ui-03-cypress 入门介绍

cypress 是什么? 简而言之,Cypress 是一款专为现代Web构建的下一代前端测试工具。我们解决了开发人员和质量保证工程师在测试现代应用程序时面临的关键问题。 我们使以下操作成为可能: 设置测试编写测试运行测试调试测试 Cypress经常与Se…

AUTOSAR软件手册文档缩写描述,AUTOSAR_TR_PredefinedNames

由于AUTOSAR文档中的缩写太多,入门者看起开不方便。例如TR、SWS、SRS、EXP模块。 下载链接:https://www.autosar.org/fileadmin/standards/R21-11/FO/AUTOSAR_TR_PredefinedNames.pdf

阿里云服务器端口PPTP 1723放行教程

阿里云服务器安装PPTP VPN需要先开通1723端口,阿里云服务器端口是在安全组中操作的,阿里云服务器网aliyunfuwuqi.com来详细说明阿里云服务器安全组开放PPTP VPN专用1723端口教程: 阿里云服务器放行1723端口教程 PPTP是点对点隧道协议&#…

用js让用户输入一个数累加和

需求&#xff1a;用户输入一个数&#xff0c; 计算 1 到这个数的和。 比如 用户输入的是 5&#xff0c; 则计算 1~5 之间的累加和 并且输出到控制台 <body><script>let numprompt(请输入一个数)let sum0for(let i1;i<num;i){sumi}console.log(sum)</script…

Windows内存取证

1.分析内存镜像&#xff0c;找到内存中的恶意进程&#xff0c;并将进程的名称作为flag值提交, 格式flag{xx} pstree 以树的形式展现进程 2.分析内存镜像&#xff0c;找到黑客访问恶意链接的时间格式flag{2023-01-19 00:00:00} 目录 1.分析内存镜像&#xff0c;找到内存中…

SAM-Track online / offline配置

segment anything model&#xff08;SAM&#xff09;是Meta于2023年4月5日发布的分割基础模型。SAM 允许分割任何对象而无需微调。 可以在这里尝试SAM模型的效果。 分割效果这么好&#xff0c;都忍不住想用SAM来做场景的语义分割&#xff0c;realtime与否先放在一边&#xff0c…

BRF文件数据结构

一.BRF-文件头数据结构 type_mesh "mesh" 网格 type_material "material" 材质struct brf_header{int type_length; //4个字节, type字符串对应长度char* type_name; //根据type_length获取int type_content_num; //4个字节,对应类型所含个数,例如含有模…

快速入门ESP32——点亮你的第一个LCD屏幕

相关文章 快速入门ESP32——开发环境配置Arduino IDE 快速入门ESP32——开发环境配置PlatformIO IDE 快速入门ESP32—— platformIO添加开源库和自己的开发库 快速入门ESP32—— 解决platformIO添加开源库下载失败的问题 快速入门ESP32——点亮你的第一个LCD屏幕 前言一、移植T…

【Bootstrap学习 day7】

Bootstrap按钮 按钮样式 使用.btn相关类实现 <button type"button" class"btn">基本按钮</button> <button type"button" class"btn btn-primary">主要按钮</button> <button type"button" cl…

【linux】ufw 的基本使用

碎碎念 所有的云平台的网络流量的进出基本上有三层&#xff0c;首先是虚拟网的流量控制&#xff0c;一般是通过子网访问控制列表来控制vpc也好子网也好的流量出入&#xff0c;其次是安全组控制一层&#xff0c;通过安全组规则控制一类/一组主机&#xff08;指EC2/ECS/VM/CE这些…

单机游戏数据自动保存方案

引言 单机游戏数据的自动保存方案 大家好&#xff0c;2023年还有最后的3天&#xff01; 有小伙伴私信我&#xff0c;说: 总感觉一股脑的全盘定时保存不科学&#xff0c;也写过保存变化的玩家数据&#xff0c;但是改完数据就得手动标记一下字段变化&#xff0c;感觉不够智能&…

Linux程序、进程以及计划任务

目录 一、程序和进程 1、什么是程序&#xff1f; 2、什么是进程&#xff1f; 3、线程是什么&#xff1f; 4、如何查看是多线程还是单线程 5、进程结束的两种情况&#xff1a; 6、进程的状态 二、查看进程信息的相关命令 1、ps&#xff1a;查看静态的进程统计信息 2、…