# 操作系统实验一
# 前情提要:
其实这篇文章并不会完全告诉你操作系统实验一的全部答案,只会记录一些该实验的坑爹点
如果你的实验一开头和下面这段文字一样,那么,强烈建议你看看这篇文章,最重要的一点,不要一开始点击 1-1.cpp 的编译运行,如果你点了。。。那我会为你默哀一秒钟,然后你可以重启电脑了
好了,说了这么多废话,先看看实验一的开头:
1. 背景知识
Windows 所创建的每个进程都从调用 CreateProcess () API 函数开始,该函数的任务是在对象管理器子系统内初始化进程对象。每一进程都以调用 ExitProcess () 或 TerminateProcess () API 函数终止。通常应用程序的框架负责调用 ExitProcess () 函数,对于 C++ 运行库来说,这一调用发生在应用程序的 main () 函数返回之后。
1. 创建进程
CreateProcess () 调用的核心参数是可执行文件运行时的文件名及其命令行。表 1-1 详细地列出了每个参数的类型和名称。
表 1-1 实验记录表
参数名称 | 使用目的 |
---|---|
LPCTSTR lpApplivationNAME | 全部或部分地指明包括可执行代码的 EXE 文件的文件名 |
LPCTSTR lpCommandLine | 向可执行文件发送的参数 |
LPSECURIITY_ATTRIBUTESlpProcessAttributes | 返回进程句柄的安全属性,主要指明这一句柄是否应该由其他子进程所继承。 |
LPSECURIITY_ATTRIBUTESlpThreadAttributes | 返回进程的主线程的句柄的安全属性 |
BOOL bInheritHandle | 一种标志,告诉系统允许新进程继承创建者进程的句柄 |
DWORD dwCreationFlage | 特殊的创建标志(如 CREATE_SUSPENDED)的位标记 |
LPVOID lpEnvironment | 向新进程发送的一套环境变量;如为 null 值则发送调用者环境 |
LPCTSTR lpCurrentDirectory | 新进程的启动目录 |
STARTUPINFO lpStartupInfo | STARTUPINFO 结构,包括新进程的输入和输出配置的详情 |
LPPROCESS_INFORMATION lpProcessInformation | 调用的结果块;发送新应用程序的进程和主线程的句柄和 ID |
OK,假如到这里都是一模一样的,那么接着往下看吧,如果没有,慢走不送
# 一、执行如下指令 C:\ CL 1-1.cpp,给出运行结果,并进行分析
看起来是不是很简单,只要在命令行里输入上面的句子就结束了,那我只能说你太天真了。
cl 指令是 VS(全名 Visual Studio)才包含的,也就是如果你的电脑上没有下 VS,那么这个问题你没法做
# 1、第一步,下载 VS,找到 cl.exe 所在文件夹
在安装 VS 时,你需要选择安装有关 C/C++ 开发有关的库才可以
笔者本人的 cl.exe 在 F:\dev C\VS\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64
将这个目录添加到你系统变量的 Path 中,然后你打开 cmd 可以尝试一下输入以下命令:
C:\Users\asus>cl |
如果出现了以下界面:
那么证明你的 cl.exe 已经放入系统路径中了
# 2、第二步,将你的系统中的一些库添加到系统变量中
记住,是添加到系统变量中,而不是系统变量的 Path 中
新建变量 Lib:
添加路径包含:C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt\x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\ucrt_enclave\x64
C:\Program Files (x86)\Windows Kits\10\Lib\10.0.22621.0\um\x64
F:\dev C\VS\VC\Tools\MSVC\14.37.32822\lib\x64
新建变量 Include:
添加路径包含:F:\dev C\VS\VC\Tools\MSVC\14.37.32822\include
C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\cppwinrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\shared
C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\ucrt
C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\um
C:\Program Files (x86)\Windows Kits\10\Include\10.0.22621.0\winrt
# 3、第三步,如果你再次运行 CL 1-1.cpp 后出现了问题
问题描述大概就是找不到 mspdbcore.dll 文件,那么按照一下步骤解决
进入文件夹 F:\dev C\VS\Common7\IDE
将四个文件复制 msobj140.dll,mspdb140.dll,mspdbcore.dll,mspdbsrv.exe
到文件夹 F:\dev C\VS\VC\Tools\MSVC\14.37.32822\bin\Hostx64\x64 中,选择覆盖文件
# 4、第四步,正常运行,不出意外的话可以得到以下结果:
到这里第一问才完整解决,那么剩下的问题我不会记录答案,下面会记录 1-1.cpp 的完整代码,如果你的和下面不一样,说明你的代码可能有 bug:
// proccreate项目
#include <windows.h>
#include <iostream>
#include <stdio.h>
// 创建传递过来的进程的克隆过程并赋于其ID值
void StartClone(int nCloneID)
{
// 提取用于当前可执行文件的文件名
TCHAR szFilename[MAX_PATH] ;
:: GetModuleFileName(NULL, szFilename, MAX_PATH) ;
// 格式化用于子进程的命令行并通知其EXE文件名和克隆ID
TCHAR szCmdLine[MAX_PATH];
:: sprintf(szCmdLine,"\"%s\" %d",szFilename,nCloneID);
// 用于子进程的STARTUPINFO结构
STARTUPINFO si;
:: ZeroMemory(reinterpret_cast <void*> (&si) , sizeof(si) ) ;
si.cb = sizeof(si) ; // 必须是本结构的大小
// 返回的用于子进程的进程信息
PROCESS_INFORMATION pi;
// 利用同样的可执行文件和命令行创建进程,并赋于其子进程的性质
BOOL bCreateOK=::CreateProcess(
szFilename, // 产生这个EXE的应用程序的名称
szCmdLine, // 告诉其行为像一个子进程的标志
NULL, // 缺省的进程安全性
NULL, // 缺省的线程安全性
FALSE, // 不继承句柄
CREATE_NEW_CONSOLE, // 使用新的控制台
NULL, // 新的环境
NULL, // 当前目录
&si, // 启动信息
&pi) ; // 返回的进程信息
// 对子进程释放引用
if (bCreateOK)
{
:: CloseHandle(pi.hProcess) ;
:: CloseHandle(pi.hThread) ;
}
return;
}
int main(int argc, char* argv[] )
{
// 确定进程在列表中的位置
int nClone(0) ; // 等价于 int nClone = 0
if (argc > 1)
{
// 从第二个参数中提取克隆ID
:: sscanf(argv[1] , "%d" , &nClone) ;
}
// 显示进程位置
std :: cout << "Process ID:" << :: GetCurrentProcessId()
<< ", Clone ID:" << nClone
<< std :: endl;
// 检查是否有创建子进程的需要
const int c_nCloneMax=25;
if (nClone < c_nCloneMax)
{
// 发送新进程的命令行和克隆号
StartClone(++nClone) ;
}
// 在终止之前暂停一下 (l/2秒)
:: Sleep(500) ;
return 0;
}