进程控制实验
1. 实验目的
设计并实现Unix的”time“命令,该命令通过命令行参数接受要运行的程序,创建一个独立的进程来运行该程序,并记录程序运行时间。
2. 实验内容
2.1 Windows实现
(1)使用CreateProcess()
来创建进程运行指定可执行文件
(2)在父进程中使用WaitForSingleObject()
在命令中和新创建的进程之间同步
(3)调用GetSystemTime()
获取子进程运行时间
(4)将获得的运行时间格式化输出
2.2 macOS实现
(1)使用fork()
创建子进程
(2)使用execv()
指定子进程执行的程序
(3)父进程使用wait()
等待子进程结束
(4)调用gettimeofday()
获取子进程运行时间
(5)将获取的运行时间格式化输出
3. 实验环境
本实验基于本机macOS系统和Windows虚拟机完成,具体实验环境如下:
3.1 Linux环境
Linux环境配置如下:
- 操作系统:macOS
- 内存容量:8GB
- 处理器:2.9GHz Intel Core i5
- 硬盘容量:500GB
3.2 虚拟机环境
Windows虚拟机环境配置如下:
- 虚拟机软件:VMware Fusion 11
- 虚拟机操作系统:Windows 7 旗舰版
- 虚拟机内存:4GB
- 虚拟机硬盘容量:60GB
4. 程序设计和实现
4.1 Windows实现
4.1.1 API介绍
进程创建函数
本实验使用CreateProcess()
函数创建进程并为进程指定运行程序。其语句调用如下:
#include<windows.h>
BOOL CreateProcess(LPCTSTR lpApplicationName, LPTSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles, DWORD dwCreationFlag,
LPVOID lpEnvironment, LPCTSTR lpCurrentDirectory,
LPSTARTUPINFO lpStartupInfo,
LPPROCESS_INFORMTION lpProcessInformation);
该函数参数过多,本实验中多没用到,仅用到了部分参数,以下介绍几个有用到的参数。
lpApplication
:该参数指定新进程将使用的可执行文件
lpCommandLine
:该参数指定里传递给新进程的命令行字符串,该函数将按照一定的顺序搜索该可执行文件位置,并执行
lpProcessInformation
:该参数是只想包含返回的进程和线程的句柄、进程和线程标识符的指针。在等待同步函数中需要从该结构中调取句柄信息
进程等待同步函数
本实验使用WaitForSingleObject()
函数使父进程等待子进程,函数描述如下:
DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);
其中,参数hHandle
为等待对象的句柄,实验中通过lpProcessInformation.hProcess
给出,dwMillisenconds
是以毫秒为单位的等待时间,由于本实验等待子进程完全结束,于是给定值为无限,即INFINITE
。
计时函数
本实验使用GetSystemTime()
进行计时,函数描述如下:
void GetSystemTime(
LPSYSTEMTIME lpSystemTime
);
其参数是一个指向SYSTEMTIME
结构体的指针,该函数使用的是一个UTC时间,并非本地时间。
使用该函数需要定义SYSTEMTIME
结构体提供记录,在输出时需要对时间进行格式化处理,具体如下:
SYSTEMTIME start,end;
GetSystemTime(&start); //记录开始时间
/* Running code */
GetSystemTime(&end); //记录结束时间
int hours=end.wHour-start.wHour; //登记小时差
int minutes=end.wMinute-start.wMinute; //登记分钟差
int seconds=end.wSecond-start.wSecond; //登记秒差
int milliseconds=end.wMillisecond-start.wMillisecond; //登记毫秒差
4.1.2 程序代码
本实验程序主要代码mytime.cpp
,程序源代码如下:
#include <stdio.h>
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char const *argv[])
{
SYSTEMTIME start,end;
STARTUPINFO si;
ZeroMemory(reinterpret_cast<void*>(&si),sizeof(si));//初始化lpStartUpInfo参数
si.cb=sizeof(si);
PROCESS_INFORMATION pi; //初始化lpProcessInformation参数
TCHAR szFilename[MAX_PATH];
sprintf(szFilename,"%s",argv[1]); //初始化lpApplicationName参数
TCHAR szCmdLine[MAX_PATH