张林计算机操作系统实验.pdf
操 作 系 统 实 验 指 导目 录 1、Windows 2 000进 程 观 测(2 学 时)2、Windows 2000进 程 控 制(2 学 时)3、Windows 2000线 程 同 步(2 学 时)4、Windows 2000线 程 间 通 信(2 学 时)5、Windows 2000内 存 结 构(4 学 时)实 验 一 Windows 2000进 程 观 测 一、背 景 知 识 Windows 2000可 以 识 别 的 应 用 程 序 包 括 控 制 台 应 用 程 序、G U I应 用 程 序 和 服 务 应 用 程 序。控 制 台 应 用 程 序 可 以 创 建 GUI,G U I应 用 程 序 可 以 作 为 服 务 来 运 行,服 务 也 可 以 向 标 准 的 输 出 流 写 入 数 据。不 同 类 型 应 用 程 序 间 的 惟 一 重 要 区 别 是 其 启 动 方 法。Windows 2000是 以 N T的 技 术 构 建 的,它 提 供 了 创 建 控 制 台 应 用 程 序 的 能 力,使 用 户 可 以 利 用 标 准 的 C+工 具,如 iostream库 中 的 cout和 c in对 象,来 创 建 小 型 应 用 程 序。当 系 统 运 行 时,Windows 2000的 服 务 通 常 要 向 系 统 用 户 提 供 所 需 功 能。服 务 应 用 程 序 类 型 需 要 ServiceMail。函 数,由 服 务 控 制 管 理 器(S C M)加 以 调 用。SC M是 操 作 系 统 的 集 成 部 分,负 责 响 应 系 统 启 动 以 开 始 服 务、指 导 用 户 控 制 或 从 另 一 个 服 务 中 来 的 请 求。其 本 身 负 责 使 应 用 程 序 的 行 为 像 一 个 服 务。通 常,服 务 登 录 到 特 殊 的 LocalSystem账 号 下,此 账 号 具 有 与 开 发 人 员 创 建 的 服 务 不 同 的 权 限。当 令 C+编 译 器 创 建 可 执 行 程 序 时,编 译 器 将 源 代 码 编 译 成 O B J文 件,然 后 将 其 与 标 准 库 相 链 接。产 生 的 EX E文 件 是 装 载 器 指 令、机 器 指 令 和 应 用 程 序 的 数 据 的 集 合。装 载 器 指 令 告 诉 系 统 从 哪 里 装 载 机 器 代 码。另 一 个 装 载 器 指 令 告 诉 系 统 从 哪 里 开 始 执 行 进 程 的 主 线 程。在 进 行 某 些 设 置 后,进 入 开 发 者 提 供 的 m ain()、ServiceM ain()或 W inM ain()函 数 的 低 级 入 U点。机 器 代 码 中 包 括 有 控 制 逻 辑,它 所 做 的 事 包 括 跳 转 到 Windows A P I函 数,进 行 计 算 或 向 磁 盘 写 入 数 据 等。Windows允 许 开 发 人 员 将 大 型 应 用 程 序 分 为 较 小 的、互 相 有 关 系 的 服 务 模 块,即 动 态 链 接 库(D L L)代 码 块,在 其 中 包 含 应 用 程 序 所 使 用 的 机 器 代 码 和 应 用 程 序 的 数 据。二、实 验 目 的 通 过 对 Windows 2000编 程,进 一 步 熟 悉 操 作 系 统 的 基 本 概 念,较 好 地 理 解 Windows 2000的 结 构。三、实 验 内 容 与 步 骤 1.简 单 的 控 制 台 应 用 程 序 我 们 先 来 创 建 一 个 名 为“Hello,World”的 应 用 程 序。步 骤 1:登 录 进 入 W indow s操 作 系 统。步 骤 2:启 动 ViuralC+6.01File(文 件)-New(新 建),P ro ject(项 目)-Win32 console Application(Win32 控 制 台 项 目)然 后 填 写 Project name:example 1Location:则 开 始 进 入 Win32 Console Application向 导 程 序 选 择 An empty project;此 时 创 建 一 个 新 的 W in32控 制 台 空 项 目。File(文 件)-New(新 建)-Files(文 件)-C+source files确 认 Add to project:example 1填 写 File:Hello.cpp最 后 选 取“OK”步 骤 3:将 清 单 1-1中 的 程 序 键 入。清 单 1-1 一 个 简 单 的 Windows 2000控 制 台 应 用 程 序/hello 项 目#include void main()std:cout”Hello,Windows 2000 std:endl;步 骤 4:编 译 生 成 H ello.E X E,并 执 行 操 作 能 否 正 常 进 行?如 果 不 行,则 可 能 的 原 因 是 什 么?运 行 结 果:能,Hello,Windows 2000步 骤 5:运 行 Hello.EXE程 序,产 生 用 户 键 入 的 一 行 文 字。运 行 结 果:2.GUI应 用 程 序 在 下 面 的 实 验 中,C+编 译 器 创 建 一 个 G U I应 用 程 序,代 码 中 包 括 了 W inM ainO方 法,这 是 G U I类 型 的 应 用 程 序 的 标 准 入 口 点。步 骤 1:File(文 件)-New(新 建)-Project(项 目)-Win32 Application(Win32 应 用 项 目)2然 后 填 写 Project name:example2Location:则 开 始 进 入 Win32 Application向 导 程 序 选 择 An empty project;此 时 创 建 一 个 新 的 W in32应 用 空 项 目。File(文 件)-New(新 建)-Files(文 件)C+source files确 认 Add to project:example2填 写 File:l-2.cpp最 后 选 取“OK”步 骤 2:将 清 单 1-2中 的 程 序 键 入。清 单 1-2 Windows 2000的 GUI应 用 程 序/msgbox 项 目#include/标 准 的 include/告 诉 连 接 器 与 包 括 MessageBoxAPI函 数 的 user32库 进 行 连 接#pragma comment(lib,ttuser32.1ibM)/这 是 个 可 以 弹 印 信 息 框 然 后 退 出 的 筒 单 的 应 用 程 序 int APIENTRY WinMain(HINSTANCEHINSTANCELPSTRint(:MessageBox(NULL,“Hello,Windows 2000”,“Greetings”,MB_OK);/*hlnstance*/,I*hPrevInstance*/,/*IpCmdLine*/,/*nCmdShow*/)/没 有 父 窗 口/消 息 框 中 的 文 本/消 息 框 标 题/其 中 只 有 一 个 O K按 钮/返 回 0 以 便 通 知 系 统 不 进 入 消 息 循 环 return(O);)3步 骤 3 编 译 生 成 1-2.E X E,并 执 行 或 在“命 令 提 示 符”窗 口 运 行 1-2.EXE文 件:C:1-2.EXE运 行 结 果(试 将 其 中 的 信 息 与 清 单 3-1程 序 的 运 行 结 果 进 行 比 较):_都 弹 出 一 个 对 话 框 hello,wi ndo ws2000_在 清 单 1-2的 GU I应 用 程 序 中,首 先 需 要 Windows.h头 文 件,以 便 获 得 传 送 给 W inM ain()和 MessageBox()A P I函 数 的 数 据 类 型 定 义。接 着 的 pragma指 令 指 示 编 译 器/连 接 器 找 到 User32.LIB库 文 件 并 将 其 与 产 生 的 EXE文 件 连 接 起 来。这 样 就 可 以 运 行 简 单 的 命 令 行 命 令 CL MsgBox.CPP来 创 建 这 一 应 用 程 序,如 果 没 有 pragma指 令,则 MessageBox()A P I函 数 就 成 为 未 定 义 的 了。这,指 令 是 Visual Studio C+编 译 器 特 有 的。接 下 来 是 W inM ain()方 法。其 中 有 四 个 由 实 际 的 低 级 入 口 点 传 递 来 的 参 数。hlnstance参 数 用 来 装 入 与 代 码 相 连 的 图 标 或 位 图 类 的 资 源,无 论 何 时,都 可 用 GetModuleHandle()API函 数 将 这 些 资 源 提 取 出 来。系 统 利 用 实 例 句 柄 来 指 明 代 码 和 初 始 的 数 据 装 在 内 存 的 何 处。句 柄 的 数 值 实 际 上 是 E X E文 件 映 像 的 基 地 址,通 常 为 0 x00400000。下 一 个 参 数 hPrevInstance是 为 向 后 兼 容 而 设 的,现 在 系 统 将 其 设 为 NULL。应 用 程 序 的 命 令 行(不 包 括 程 序 的 名 称)是 IpCmdLine参 数。另 外,系 统 利 用 nCmdShow参 数 告 诉 应 用 程 序 如 何 显 示 它 的 主 窗 口(选 项 包 括 最 小 化、最 大 化 和 正 常)。最 后,程 序 调 用 MessageBoxOAPI函 数 并 退 出。如 果 在 进 入 消 息 循 环 之 前 就 结 束 运 行 的 话,最 后 必 须 返 回 0。3.进 程 对 象 操 作 系 统 将 当 前 运 行 的 应 用 程 序 看 作 是 进 程 对 象。利 用 系 统 提 供 的 惟 一 的 称 为 句 柄(HAN DLE)的 号 码,就 可 与 进 程 对 象 交 互。这 一 号 码 只 对 当 前 进 程 有 效。本 实 验 表 示 了 一 个 简 单 的 进 程 句 柄 的 应 用。在 系 统 中 运 行 的 任 何 进 程 都 可 调 用 GelCurrentProcess()A P I函 数,此 函 数 可 返 回 标 识 进 程 本 身 的 句 柄。然 后 就 可 在 W indows需 要 该 进 程 的 有 关 情 况 时,利 用 这 一 句 柄 来 提 供。步 骤 1:File(文 件)-New(新 建)-Project(项 目)-Win32 console Application(Win32 控 制 台 4项 目)然 后 填 写 Project name:example3Location:则 开 始 进 入 Win32 Console Application向 导 程 序 选 择 An empty project;此 时 创 建 一 个 新 的 W in32控 制 台 空 项 目。File(文 件)-New(新 建)-Files(文 件)-C+source files确 认 Add to project:example 1填 写 File:Hello.cpp最 后 选 取“OK”步 骤 2:将 清 单 1-3中 的 程 序 键 入。清 单 3 获 得 和 使 用 进 程 的 句 柄/prochandle 项 目#include#include/确 定 自 己 的 优 先 权 的 简 单 应 用 程 序 void main()(/从 当 前 进 程 中 提 取 句 柄 HANDLE hProcessThis=:GetCurrentProcess();/请 求 内 核 提 供 该 进 程 所 属 的 优 先 权 类 DWORD dwPriority=:GetPriorityClass(hProcessThis);/发 出 消 息,为 用 户 描 述 该 类 std:cout”Current process priority:;switch(dwPriority)(case HIGH_PRIORITY_CLASS:std:cout H igh;break;case NORMAL_PRIORITY_CLASS:5std:cout ttNormaF,;break;case IDLE_PRIORITY_CLASS:std:cout“Idle”;break;case REALTIME_PRIORITY_CLASS:std:cout”Realtime”;break;default:std:cout“unknown”;break;)std:cout std:endl;)清 单 1-3中 列 出 的 是 一 种 获 得 进 程 句 柄 的 方 法。对 于 进 程 句 柄 可 进 行 的 惟 一 有 用 的 操 作 是 在 A P I调 用 时,将 其 作 为 参 数 传 送 给 系 统,正 如 清 单 1-3中 对 GetPriorityClassO A P I函 数 的 调 用 那 样。在 这 种 情 况 下,系 统 向 进 程 对 象 内“窥 视”,以 决 定 其 优 先 级,然 后 将 此 优 先 级 返 回 给 应 用 程 序。OpenProcess()和 CreateProcess()A P I函 数 也 可 以 用 于 提 取 进 程 句 柄。前 者 提 取 的 是 已 经 存 在 的 进 程 的 句 柄,而 后 者 创 建 一 个 新 进 程,并 将 其 句 柄 提 供 出 来。步 骤 3:编 译 生 成 1-3.E X E,并 执 行 或 在“命 令 提 示 符”窗 口 运 行 1-3.EXE文 件:运 行 结 果:Current process priority:N ormal_步 骤 4:File(文 件)-New(新 建)-Project(项 目)-Win32 console Application(Win32 控 制 台 项 目)然 后 填 写 Project name:example3Location:则 开 始 进 入 Win32 Console Application向 导 程 序 选 择 An empty project;此 时 创 建 一 个 新 的 W in32控 制 台 空 项 目。File(文 件)-New(新 建)-Files(文 件 又 C+source Ries6确 认 Add to project:example 1填 写 File:Hello.cpp最 后 选 取“OK”步 骤 5:将 清 单 1-4中 的 程 序 键 入。清 单 1-4显 示 如 何 找 出 系 统 中 正 在 运 行 的 所 有 进 程,如 何 利 用 OpenProcess()A P I函 数 来 获 得 每 一 个 访 问 进 程 的 进 一 步 信 息。清 单 4 利 用 句 柄 查 出 进 程 的 详 细 信 息/proclist 项 目#include windows.h#include#include/当 在 用 户 模 式 机 内 核 模 式 下 都 提 供 所 耗 时 间 时,在 内 核 模 式 下 进 行 所 耗 时 间 的 6 4 位 计 算 的 帮 助 方 法 DWORD GetKernelModePercentage(const FILETIME&ftKemel,const FILETIME&ftUser)(/将 FILETIME结 构 转 化 为 6 4位 整 数 ULONGLONG qwKernel=(ULONGLONG)ftKernel.dwHighDateTime)32)+ftKernel.dwLowDateTime;ULONGLONG qwUser=(ULONGLONG)ftUser.dwHighDateTime)32)+ftUser.dwLowDateTime;/将 消 耗 时 间 相 加,然 后 计 算 消 耗 在 内 核 模 式 下 的 时 间 百 分 比 ULONGLONG qwTotal=qwKernel+qwUser;DWORD dwPct=(DWORD)(ULONGLONG)100*qwKemel)/qwTotal);return(dwPct);7/以 下 是 将 当 前 运 行 进 程 名 和 消 耗 在 内 核 模 式 下 的 时 间 百 分 数 都 显 示 出 来 的 应 用 程 序 void main()/对 当 前 系 统 中 运 行 的 进 程 拍 取“快 照”HANDLE hSnapshot=:CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,/提 取 当 前 进 程 0);/如 果 是 当 前 进 程,就 将 其 忽 略/初 始 化 进 程 入 口 PROCESSENTRY32 pe;:ZeroMemory(&pe,sizeof(pe);pe.dwSize=sizeof(pe);/按 所 有 进 程 循 环 BOOL bMore=:Process32First(hSnapshot,&pe);while(bMore)(/打 开 用 于 读 取 的 进 程 if(hProcess!=NULL)(HANDLE hProcess=:OpenProcess(PROCESS_QUERYJNFORMATION,/指 明 要 得 到 信 息 FALSE,/不 必 继 承 这,句 柄 pe.th32ProcessID);/要 打 开 的 进 程/找 出 进 程 的 时 间 FILETIME ftCreation,ftExit,ftKernelMode,ftUserMode;:GetProcessTimes(hProcess,/所 感 兴 趣 的 进 程&ftCreation,/进 程 的 启 动 时 间(绝 对 的)&ftExit,/结 束 时 间(如 果 有 的 话)&ftKernelMode,/在 内 核 模 式 下 消 耗 的 时 间&ftUserMode);/在 用 户 模 式 下 消 耗 的 时 间/计 算 内 核 模 式 消 耗 的 时 间 百 分 比 8DWORD dwPctKemel=:GetKemelModePercentage(ftKemelMode,在 内 核 模 式 上 消 耗 的 时 间 ftUserMode);/在 用 户 模 式 下 消 耗 的 时 间/向 用 户 显 示 进 程 的 某 些 信 息 std:cout”Process ID:vv pe.th32ProcessID“,EXE file:vv pe.szExeFile“,%in kernel mode:vv dwPctKernel std:endl;/消 除 句 柄:CloseHandle(hProcess);)/转 向 下 一 个 进 程 bMore=:Process32Next(hSnapshot,&pe);)清 单 1一 4 程 序 首 先 利 用 Windows 2000的 新 特 性,即 工 具 帮 助 库 来 获 得 当 前 运 行 的 所 有 进 程 的 快 照。然 后 应 用 程 序 进 入 快 照 中 的 每 一 个 进 程,得 到 其 以 PROCESSENTRY32结 构 表 示 的 属 性。这 一 结 构 用 来 向 OpenProcess。A P I函 数 提 供 进 程 的 ID。Windows跟 踪 每 一 进 程 的 有 关 时 间,示 例 中 是 通 过 打 开 的 进 程 句 柄 和 GetProcessTimes()A PI来 直 询 得 到 有 关 时 间 的。接 下 来,一 个 定 制 的 帮 助 函 数 取 得 了 几 个 返 回 的 数 值,然 后 计 算 进 程 在 内 核 模 式 下 消 耗 的 时 间 占 总 时 间 的 百 分 比。程 序 的 其 余 部 分 比 较 简 单,只 是 将 有 关 信 息 显 示 给 用 户,清 除 进 程 句 柄,然 后 继 续 循 环,直 到 所 有 进 程 都 计 算 过 为 止。步 骤 6:编 译 生 成 1-4.E X E,并 执 行 或 在“命 令 提 示 符 窗 口 运 行 1-4.EXE文 件 运 行 结 果:_步 骤 7:按 下 ctrl+alt+del启 动 任 务 管 理 器,查 看 进 程 相 关 的 相 关 信 息,与 I 4.ex e的 运 行 结 果 有 何 不 同。9直 接 在 C+运 行 是 使 用 vcspawn.exe进 程,用 命 令 提 示 符 运 行 是 使 用 cm d进 程 实 验 二 Windows 2000进 程 控 制 一、背 景 知 识 Windows所 创 建 的 每 个 进 程 都 从 调 用 CreateProcess()A P I函 数 开 始,该 函 数 的 任 务 是 在 对 象 管 理 器 子 系 统 内 初 始 化 进 程 对 象。每 进 程 都 以 调 用 ExitProcess()或 TerminateProcess()A P I函 数 终 止。通 常 应 用 程 序 的 框 架 负 责 调 用 ExitProcess()函 数。对 于 C+运 行 库 来 说,这 一 调 用 发 生 在 应 用 程 序 的 main。函 数 返 回 之 后。1.创 建 进 程 CreateProcessO调 用 的 核 心 参 数 是 可 执 行 文 件 运 行 时 的 文 件 名 及 其 命 令 行。表 2-1详 细 地 列 出 了 每 个 参 数 的 类 型 和 名 称。表 2 T C reateP rocess()函 数 的 参 数 参 数 名 称 使 用 目 的 LPCTSTR IpApplivationName 全 部 或 部 分 地 指 明 包 括 可 执 行 代 码 的 EX E文 件 的 文 件 名 LPCTSTR IpCommandLine 向 可 执 行 文 件 发 送 的 参 数 LPSECURHTY_ATTRIBUTESIpProcessAttributes返 回 进 程 句 柄 的 安 全 属 性。主 要 指 明 这 一 句 柄 是 否 应 该 由 其 他 子 进 程 所 继 承 LPSECURIITY_ATTRIBUTESIpThreadAttributes返 回 进 程 的 主 线 程 的 句 柄 的 安 全 属 性 BOOL blnheritHandle 一 种 标 志,告 诉 系 统 允 许 新 进 程 继 承 创 建 者 进 程 的 句 柄 DWORD dwCreationFlage 特 殊 的 创 建 标 志(如 CREATE_SUSPENDED)的 位 标 记 LPVOID IpEnvironment 向 新 进 程 发 送 的 一 套 环 境 变 量;如 为 null值 则 发 送 调 用 者 环 境 LPCTSTR IpCurrentDirectory 新 进 程 的 启 动 目 录 STARTUPINFO IpStartupInfo STARTUPINFO结 构,包 括 新 进 程 的 输 入 和 输 出 配 置 的 详 情 LPPROCESSJNFORMATIONIpProcessInformation调 用 的 结 果 块;发 送 新 应 用 程 序 的 进 程 和 主 线 程 的 句 柄 和 ID可 以 指 定 第 一 个 参 数,即 应 用 程 序 的 名 称,其 中 包 括 相 对 于 当 前 进 程 的 当 前 目 录 的 全 路 径 10或 者 利 用 搜 索 方 法 找 到 的 路 径;IpCommandLine参 数 允 许 调 用 者 向 新 应 用 程 序 发 送 数 据;接 下 来 的 三 个 参 数 与 进 程 和 它 的 主 线 程 以 及 返 回 的 指 向 该 对 象 的 句 柄 的 安 全 性 有 关。然 后 是 标 志 参 数,用 以 在 dwCreationFlags参 数 中 指 明 系 统 应 该 给 予 新 进 程 什 么 行 为。经 常 使 用 的 标 志 是 CREATE_SUSPNDED,告 诉 主 线 程 立 刻 暂 停。当 准 备 好 时,应 该 使 用 ResumeThreadO A P I来 启 动 进 程。另 一 个 常 用 的 标 志 是 CREATE_NEW_CONSOLE,告 诉 新 进 程 启 动 自 己 的 控 制 台 窗 口,而 不 是 利 用 父 窗 口。这 一 参 数 还 允 许 设 置 进 程 的 优 先 级,用 以 向 系 统 指 明,相 对 于 系 统 中 所 有 其 他 的 活 动 进 程 来 说,给 此 进 程 多 少 C P U时 间。接 着 是 CreateProcessO函 数 调 用 所 需 要 的 三 个 通 常 使 用 缺 省 值 的 参 数。第-个 参 数 是 IpEnvironment参 数,指 明 为 新 进 程 提 供 的 环 境;第 二 个 参 数 是 IpCurrentDirectory,可 用 于 向 主 创 进 程 发 送 与 缺 省 目 录 不 同 的 新 进 程 使 用 的 特 殊 的 当 前 目 录;第 三 个 参 数 是 STARTUPINFO数 据 结 构 所 必 需 的,用 于 在 必 要 时 指 明 新 应 用 程 序 的 主 窗 口 的 外 观。CreateProcessO的 最 后 一 个 参 数 是 用 于 新 进 程 对 象 及 其 主 线 程 的 句 柄 和 1 D 的 返 回 值 缓 冲 区。以 PROCESS_INFORMATK)N结 构 中 返 回 的 句 柄 调 用 CloseHandle()API函 数 是 重 要 的,因 为 如 果 不 将 这 些 句 柄 关 闭 的 话,有 可 能 危 及 主 创 进 程 终 止 之 前 的 任 何 未 释 放 的 资 源。2.正 在 运 行 的 进 程 如 果 一 个 进 程 拥 有 至 少 一 个 执 行 线 程,则 为 正 在 系 统 中 运 行 的 进 程。通 常,这 种 进 程 使 用 主 线 程 来 指 示 它 的 存 在。当 主 线 程 结 束 时,调 用 ExitProcessO A P I函 数,通 知 系 统 终 止 它 所 拥 有 的 所 有 正 在 运 行、准 备 运 行 或 正 在 挂 起 的 其 他 线 程。当 进 程 正 在 运 行 时,可 以 查 看 它 的 许 多 特 性,其 中 少 数 特 性 也 允 许 加 以 修 改。首 先 可 查 看 的 进 程 特 性 是 系 统 进 程 标 识 符(P I D),可 利 用 GetCurrentProcessIdO A P I函 数 来 查 看,与 GetCurrentProcess。相 似,对 该 函 数 的 调 用 不 能 失 败,但 返 回 的 PID在 整 个 系 统 中 都 可 使 用。其 他 的 可 显 示 当 前 进 程 信 息 的 A P I函 数 还 有 GetStartupInfo()和 GelProcessShutdownParameters(),可 给 出 进 程 存 活 期 内 的 配 置 详 情。通 常,一 个 进 程 需 要 它 的 运 行 期 环 境 的 信 息。例 如 A P I函 数 GetModuleFileName()和 GetCommandLine(),可 以 给 出 用 在 CreateProcessO中 的 参 数 以 启 动 应 用 程 序。在 创 建 应 用 程 序 时 可 使 用 的 另 一 个 A P I函 数 是 IsDebuggerPresent。可 利 用 A P I函 数 GetGuiResourcesO来 查 看 进 程 的 G U I资 源。此 函 数 既 可 返 回 指 定 进 程 中 的 打 开 的 G U I对 象 的 数 目,也 可 返 回 指 定 进 程 中 打 开 的 USER对 象 的 数 目。进 程 的 其 他 性 能 信 息 可 通 过 GetProcessIoCounters()、GetProcessPriorityBoost()、G etProcessTim es()和 GetProcessWorkingSetSize()A P I得 到。以 上 这 几 个 A P I函 数 都 只 需 要 具 有 PROCESS_QUERY_INFORMATION访 问 权 限 的 指 向 所 感 兴 趣 进 程 的 句 柄。1 1另 一 个 可 用 于 进 程 信 息 查 询 的 A P I函 数 是 GetProcessVersion()。此 函 数 只 需 感 兴 趣 进 程 的 PID(进 程 标 识 号)。本 实 验 程 序 清 单 3-6中 列 出 了 这 一 A P I函 数 与 GetVersionEx()的 共 同 作 用,可 确 定 运 行 进 程 的 系 统 的 版 本 号。3.终 止 进 程 所 有 进 程 都 是 以 调 用 ExitProcess()或 者 TerminateProcess()函 数 结 束 的。但 最 好 使 用 前 者 而 不 要 使 用 后 者,因 为 进 程 是 在 完 成 了 它 的 所 有 的 关 闭“职 责”之 后 以 正 常 的 终 止 方 式 来 调 用 前 者 的。而 外 部 进 程 通 常 调 用 后 者 即 突 然 终 止 进 程 的 进 行,由 于 关 闭 时 的 途 径 不 太 正 常,有 可 能 引 起 错 误 的 行 为。TerminateProcessO A P I函 数 只 要 打 开 带 有 PROCESS_TERMINATE访 问 权 的 进 程 对 象,就 可 以 终 止 进 程,并 向 系 统 返 回 指 定 的 代 码。这 是 一 种“野 蛮”的 终 止 进 程 的 方 式,但 是 有 时 却 是 需 要 的。如 果 开 发 人 员 确 实 有 机 会 来 设 计“谋 杀”(终 止 别 的 进 程 的 进 程)和“受 害”进 程(被 终 止 的 进 程)时,应 该 创 建 一 个 进 程 间 通 讯 的 内 核 对 象 如 一 个 互 斥 程 序 这 样 一 来,“受 害”进 程 只 在 等 待 或 周 期 性 地 测 试 它 是 否 应 该 终 止。二、实 验 目 的 1)通 过 创 建 进 程、观 察 正 在 运 行 的 进 程 和 终 止 进 程 的 程 序 设 计 和 调 试 操 作,进 一 步 熟 悉 操 作 系 统 的 进 程 概 念,理 解 Windows 2000进 程 的“生 2)通 过 阅 读 和 分 析 实 验 程 序,学 习 创 建 进 程、观 察 进 程 和 终 止 进 程 的 程 序 设 计 方 法。三、工 具/准 备 工 作 在 开 始 本 实 验 之 前,请 回 顾 教 科 书 的 相 关 内 容。需 要 做 以 下 准 备:1)一 台 运 行 Windows 2000 Professional操 作 系 统 的 计 算 机。2)计 算 机 中 需 安 装 Visual C+6.0专 业 版 或 企 业 版。四、实 验 内 容 与 步 骤 请 回 答:Windows所 创 建 的 每 个 进 程 都 是 以 调 用 C r e a t e P r o c e s s()API函 数 开 始 和 以 调 用 E x i t P r o c e s s()或 TerminateProcessO A P I函 数 终 止。121.创 建 进 程 本 实 验 显 示 了 创 建 子 进 程 的 基 本 框 架。该 程 序 只 是 再 一 次 地 启 动 自 身,显 示 它 的 系 统 进 程 ID和 它 在 进 程 列 表 中 的 位 置。步 骤 1:登 录 进 入 Windows 2000 Professional o步 骤 2:在“开 始”菜 单 中 单 击“程 序”-Microsoft Visual Studio 6.0n uMicrosoft VisualC+6.0”命 令,进 入 Visual C+窗 口。步 骤 3:新 建 一 个 Win32 control appliton 空 项 目 example 1,并 添 加 C+source file:2-l.cpp。清 单 2-1创 建 子 进 程/proccreate 项 目#include#include#include/创 建 传 递 过 来 的 进 程 的 克 隆 过 程 并 赋 于 其 ID值 void StartClone(int nClonelD)(/提 取 用 于 当 前 可 执 行 文 件 的 文 件 名 TCHAR szFilenameMAX_PATH;:GetModuleFileName(NULL,szFilename,MAX.PATH);/格 式 化 用 于 子 进 程 的 命 令 行 并 通 知 其 E X E文 件 名 和 克 隆 IDTCHAR szCmdLineMAX_PATH;:sprintf(szCmdLine,ttV,%sV,%d”,szFilename,nClonelD);/用 于 子 进 程 的 STARTUPINFO结 构 STARTUPINFO si;:ZeroMemory(reinterpret_cast(&si),sizeof(si);si.cb=sizeof(si);/必 须 是 本 结 构 的 大 小/返 回 的 用 于 子 进 程 的 进 程 信 息 PROCESS_INFORMATION pi;/利 用 同 样 的 可 执 行 文 件 和 命 令 行 创 建 进 程,并 赋 于 其 子 进 程 的 性 质 13BOOL bCreateOK=:CreateProcess(szFilename,/产 生 这 个 E X E的 应 用 程 序 的 名 称 szCmdLine,/告 诉 其 行 为 像 一 个 子 进 程 的 标 志 NULL,/缺 省 的 进 程 安 全 性 NULL,/缺 省 的 线 程 安 全 性 FALSE,/不 继 承 句 柄 CREATE_NEW_.CONSOLE,/使 用 新 的 控 制 台 NULL,/新 的 环 境 NULL,/当 前 目 录&si,/启 动 信 息&pi);/返 回 的 进 程 信 息/对 子 进 程 释 放 引 用 if(bCreateOK)(:CloseHandle(pi.hProcess);:CloseHandle(pi.hThread);int main(int argc,char*argvlJ)(/确 定 进 程 在 列 表 中 的 位 置 int nClone(O);if(argc 1)/从 第 二 个 参 数 中 提 取 克 隆 ID:sscanf(argvl,“%d”,&nClone);)/显 示 进 程 位 置 std:cout”Process ID:i4:GetCurrentProcessId()”,Clone ID:4 4 nClone std:endl;14/检 查 是 否 有 创 建 子 进 程 的 需 要 const int c_nCloneMax=25;if(nClone c_nCloneMax)(/发 送 新 进 程 的 命 令 行 和 克 隆 号 StartClone(+nClone);/在 终 止 之 前 暂 停 一 下。/2 秒):Sleep(500