ARTICLE · 1115929
实验室基本技能之机器人测控软件开发二:操作系统及事件、消息、进程、线程概念(附MFC学习课件)
从程序设计的角度看,操作系统本质上是一组对硬件进行抽象、并为应用程序提供服务的系统软件。它的主要作用可以归纳为以下几方面:
一、操作系统的主要作用
进程管理负责进程的创建、调度、同步、通信和终止,让多个程序能够“同时”运行,并合理分配 CPU 时间。 内存管理为程序分配和回收内存,提供虚拟地址空间,实现地址映射、内存保护和按需调页,使程序不必直接操作物理内存。 文件管理对磁盘等存储设备上的数据进行组织,提供文件的创建、读写、删除、目录管理等接口,屏蔽底层块设备的差异。 设备管理通过驱动程序统一管理键盘、鼠标、显示器、磁盘、网卡等外设,为程序提供统一的 I/O 接口。 提供用户接口提供命令行界面(CLI)或图形用户界面(GUI),同时也提供系统调用接口,供程序请求操作系统服务。 并发与同步提供线程、锁、信号量、事件等机制,使多个执行流能够安全地共享资源。 错误检测与保护检测非法指令、越界访问、除零等异常,防止一个程序破坏其他程序或系统本身。
从程序设计角度看,操作系统最重要的价值是:抽象硬件、隔离程序、管理并发、提供可复用的系统服务。
二、Windows的多任务机制
Windows 是抢占式多任务操作系统。所谓多任务,是指系统可以在多个进程/线程之间快速切换,让用户感觉它们同时运行。
从程序角度看:
进程是资源分配的基本单位,拥有独立的虚拟地址空间。 线程是 CPU 调度的基本单位,同一进程内的线程共享地址空间和资源。 Windows 调度器按照优先级和时间片,在多个线程之间进行抢占式调度。 每个线程有自己的栈、寄存器和执行上下文;切换线程时,系统保存旧上下文、恢复新上下文。 多任务带来的问题是并发访问共享数据,因此需要临界区、互斥量、事件、信号量等同步机制。
所以,Windows 的多任务并不是“真正同时执行所有代码”,而是通过快速切换和调度,实现宏观上的并行。
三、Windows的事件机制
Windows程序与DOS程序最大区别是Windows是事件驱动运行的,不发生外部事件,程序处于Idle状态。事件和消息是与一个windows窗口关联的。因此理解windows运行机制,理解消息和事件是关键!
在 Windows 程序设计中,“事件”通常有两层含义:
1.同步事件对象
Windows 提供内核事件对象,用于线程同步:
手动重置事件:一旦触发,所有等待线程都被唤醒。 自动重置事件:触发后只唤醒一个等待线程,然后自动复位。
常用 API 如:
CreateEvent SetEvent ResetEvent WaitForSingleObject
它常用于:一个线程等待另一个线程完成某项工作。
2.用户输入事件
在 GUI 程序中,用户的键盘、鼠标操作会被系统转换成事件,例如:
鼠标移动 鼠标左键按下 键盘按下 窗口重绘 定时器到期
这些事件会进入应用程序的消息队列。
四、Windows的消息机制
Windows GUI 程序是事件驱动的。系统或用户产生的动作,会被包装成“消息”。
消息通常包括:
窗口句柄hwnd 消息类型msg 附加参数wParam 附加参数lParam 时间、鼠标位置等
例如:
流程大致是:
用户操作或系统事件产生消息。 消息进入线程的消息队列。 程序通过GetMessage从队列取消息。 TranslateMessage处理键盘字符转换。 DispatchMessage把消息发送给目标窗口的窗口过程。 窗口过程根据消息类型执行相应代码。
所以,Windows 程序的主干通常是一个“消息循环”。
五、Windows的消息映射机制
在 MFC、WTL 等框架中,为了方便处理消息,引入了“消息映射”机制。
传统 Win32 程序使用switch-case在窗口过程中判断消息:
当消息很多时,switch-case会变得臃肿。MFC 使用消息映射表,把“消息”与“处理函数”关联起来:
然后实现对应函数:
其本质是:
·框架内部仍然有一个窗口过程。
·窗口过程收到消息后,不直接写switch-case,而是查消息映射表。
·找到对应处理函数并调用。
·如果没找到,就交给基类或DefWindowProc。
这样做的优点是:
·消息处理代码更清晰。
·便于扩展和继承。
·框架可以统一处理消息分发。
六、程序,进程和线程三者的基本定义
1.程序(Program)
程序是存放在磁盘上的可执行文件,是一组指令和数据的集合。
·它是静态的,本身不会运行。
·例如:notepad.exe、chrome.exe文件本身。
·它不占用 CPU,也不拥有运行时的内存空间和资源。
可以把它理解成“一份菜谱”:菜谱本身不是做菜的过程,只是说明。
2.进程(Process)
进程是程序的一次执行实例,是操作系统进行资源分配的基本单位。
·它是动态的,有生命周期:创建、就绪、运行、阻塞、终止。
·拥有独立的虚拟地址空间、代码段、数据段、堆、栈、打开的文件、句柄等资源。
·同一个程序可以对应多个进程。例如同时打开两个记事本,就是两个进程。
可以把它理解成“按照菜谱实际做菜的一次过程”,需要占用厨房、食材、锅具等资源。
3.线程(Thread)
线程是进程内部的一个执行流,是操作系统进行CPU调度的基本单位。
·它是动态的,有自己的程序计数器、寄存器、栈。
·同一进程内的多个线程共享该进程的地址空间和资源(如堆、全局变量、打开的文件)。
·线程切换开销比进程切换小。
可以把它理解成“做菜过程中的一个具体动作”,比如一个人切菜、另一个人炒菜,他们共用同一个厨房。
4.核心区别对比
对比项 | 程序 | 进程 | 线程 |
状态 | 静态 | 动态 | 动态 |
存在位置 | 磁盘 | 内存 + 系统管理 | 内存 + 系统调度 |
是否运行 | 否 | 是 | 是 |
资源拥有 | 无 | 拥有独立资源 | 共享所属进程资源 |
地址空间 | 无 | 独立虚拟地址空间 | 共享进程地址空间 |
调度单位 | 不是 | 资源分配单位 | CPU 调度单位 |
切换开销 | 无 | 大 | 小 |
通信方式 | 无 | 进程间通信(IPC) | 直接读写共享变量 |
独立性 | 无 | 高,一个进程崩溃一般不影响其他进程 | 低,一个线程崩溃可能拖垮整个进程 |
·一个程序可以对应多个进程:双击两次记事本,就有两个进程。
·一个进程可以包含多个线程:一个进程至少有一个主线程,也可以创建多个工作线程。
·线程不能脱离进程独立存在:线程一定属于某个进程。
·进程是资源的容器,线程是执行的载体。
用一句话概括:
程序是静态的代码;进程是程序的一次执行,是资源分配单位;线程是进程内的执行流,是 CPU 调度单位。实际应用程序多数是具有多个线程,如界面线程(人机交互),工作线程(计算密集型任务)。
七、总结
操作系统在程序设计中主要承担:进程管理、内存管理、文件管理、设备管理、接口提供、并发同步和错误保护。
Windows 的多任务依靠进程/线程和抢占式调度实现;GUI 程序依靠事件驱动运行;系统把事件转换成消息放入队列;程序通过消息循环取出并分发;MFC 等框架再用消息映射把消息和处理函数关联起来,从而简化开发。
程序是磁盘上静态的指令和数据集合;进程是程序的一次动态执行、是资源分配的基本单位;线程是进程内的执行流、是 CPU 调度的基本单位;一个程序可对应多个进程,一个进程可包含多个线程,线程不能脱离进程独立存在。
八、有关学习课件和资源
有关基于Visual C++ (VS2019)的MFC学习资源见网盘:
https://pan.baidu.com/s/15mhLg6jucv9bfRXWRO3rbw
请联系dou_jp@163.com索取。