天天看点

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

一、实验目的

设计并实现Unix的“time”命令。“mytime”命令通过命令行参数接受要运行的程序,创建一个独立的进程来运行该程序,并记录程序运行的时间。

二、实验内容

在Windows下实现:

•      使用CreateProcess()来创建进程

•      使用WaitForSingleObject()在“mytime”命令和新创建的进程之间同步

•      调用GetSystemTime()来获取时间

在Linux下实现:

•      使用fork()/execv()来创建进程运行程序

•      使用wait()等待新创建的进程结束

•      调用gettimeofday()来获取时间

mytime的用法:

$ mytime.exe program1

三、实验环境

1、Windows环境下使用Dev-c++和命令行窗口!

2、Linux环境是在虚拟机中装Ubuntu15.10;如图1所示

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

图1

四、实验方法与步骤

1、在Windows下实现

(1)、在创建子进程之前先定义好各个变量,以备后续使用。

(2)、创建子进程之前调用系统函数GetSystemTime()获取当前系统时间。

(3)、调用CreateProcess()函数创建进程。

CreateProcess内的参数设置如下:

CreateProcess

 (NULL,      //不在此指定可执行文件的文件名

              argv[1],   //命令行参数

              NULL,     //默认进程安全性

              NULL,     //默认线程安全性

              FALSE,    //当前进程内的句柄不可以被子进程继承

              CREATE_NEW_CONSOLE,    //为新进程创建一个新的控制台窗口

              NULL,     //使用本进程的环境变量

              NULL,     //使用本进程的驱动器和目录

              &si, //父进程传给子进程的一些信息

              &pi  //保存新进程信息的结构

              )

注意:

最重要的三个参数,在强调一下:

(1)、由于要使用命令行来创建进程,因此CreateProcess的第一个参数设置为NULL,不在此指定可执行文件的文件名;

(2)、通过第二个参数在命令行输入一个字符串来实现创建进程;

(3)、pi是保存新进程的结构,内部包括四个参数;分别为:新创建进程的句柄,新创建进程的主线程的句柄,新创建进程的标识,新创建进程的主线程的标识。

(4)、使用命令行的形式创建好进程后,调用等待函数来等待所创建函数的死亡;

等待函数为:WaitForSingleObject(pi.hProcess,INFINITE)。

(5)、当子进程死亡后,再次通过GetSystemTime()函数获得系统时间。

(6)、用第(5)步得到的时间减去第(2)步得到的时间的时间即是生成的子进程运行时所花费的时间。

(7)、运行程序,产生mytime.exe文件。

(8)、在命令行中找到文件所放路径,比如在桌面,直接键入如下命令:

cd Desktop

mytime.exe 所要调用的子进程名

2、在Linux下实现

(1)、创建子进程之前,先取得系统时间

struct timevaltime_start;

struct timevaltime_end;

       gettimeofday(&time_start,NULL);

(2)、用fork()函数创建进程,fork()函数会返回两个值,通过这两个值来判断是子进程还是父进程。

if (fork() == 0)    //子进程

else //为父进程

(3)、①如果第(2)步中是子进程运行,则在子进程中调用execv()函数;在命令行中来运行一个程序;即execv(argv[1],&argv[1])

②如果第(2)步是父进程在运行,则先等待子进程运行结束,然后在获取时间;

即wait(NULL);

  gettimeofday(&time_end,NULL);

(4)、计算程序运行的时间(微秒):

       time_use= 1000000 * (time_end.tv_sec - time_start.tv_sec) + (time_end.tv_usec -time_start.tv_usec);

(5)、输出程序运行的时间:

printf("此程序运行的时间为:%lf微秒",time_use);

(6)、用命令gcc –o mytimemytime.c将c文件编译为可执行文件。

(7)、在终端打开编译的文件,并在其后跟上要打开的进程名;

如:桌面上的可执行文件fac(求1~20的阶乘之和):./mytime fac

五、实验结果

1、Windows环境下的实验结果

(1)、编译及运行mytime.cpp,产生mytime.exe文件的截图如下(图2所示):

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

图2

(2)、在命令行调用产生的mytime.exe文件,并在其后跟上要运行的子进程的名字,比如我自己写的GoBang这个小游戏。开始运行截图如下(图3):

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

图3

(3)GoBang这个子进程被关闭以后的截图如下(图4):

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

图4

2、Linux环境下的实验结果

(1)、mytime.c编译后的截图(图5所示)

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

图5

(2)、在终端调用可执行文件mytime,并在其后跟上要运行的子进程名,如(fac);截图如下(图6所示)

进程控制一、实验目的二、实验内容三、实验环境四、实验方法与步骤五、实验结果六、实验分析与总结七.实验源代码

图6

六、实验分析与总结

1、在Windows、Linux系统下,分别调用相应的API函数对进程进行创建、同步和获取并记录进程运行的时间,正确利用可执行文件来实现命令行创建进程。这次实验不论是linux还是windows,主要思路只有一个: 利用fork()或者createprocess()函数建立一个子进程,在建立成功之后记录运行时间,然后利用wait()或者waitforsingleobject()函数等待子进程的同步,之后再记录运行时间,用两次时间相减就可以。

2、注意的地方是,windows下的计时函数GetSystemTime()不太好用了,函数返回的是系统的时间,要用两次时间相减,这里要注意可能有负数的情况,所以要考虑借位,其实windows下面有一个好用的函数clock(),这个函数对于计时很在行。

3、收获:加深了对一些API函数的理解和应用。

七.实验源代码

Windows版本

/*题目要求:设计并实现Unix的“time”命令。“mytime”命令通过命令行参数接受要运行的程序,
			创建一个独立的进程来运行该程序,并记录程序运行的时间。
在Windows下实现:
	使用CreateProcess()来创建进程
	使用WaitForSingleObject()在“mytime”命令和新创建的进程之间同步
	调用GetSystemTime()来获取时间
*/
// 作者:野狼
// 日期:2017.3.19

#include <windows.h>
#include <stdio.h>
#include <iostream>
using namespace std;

int main(int argc, char **argv)
{
	int year, month, day, hour, minutes, seconds, milliseconds;
	SYSTEMTIME time_start, time_end;
	STARTUPINFO si;	//进程启动相关信息的结构体
	memset(&si,0,sizeof(STARTUPINFO));
	si.cb = sizeof(STARTUPINFO);	//应用程序必须将cb初始化为sizeof(STARTUPINFO)
	si.dwFlags = STARTF_USESHOWWINDOW;	//窗口标志
	si.wShowWindow = SW_SHOW;
	PROCESS_INFORMATION pi;	//必备参数设置结束

	if (!CreateProcess
	(NULL,	//不在此指定可执行文件的文件名
		argv[1],	//命令行参数
		NULL,	//默认进程安全性
		NULL,	//默认线程安全性
		FALSE,	//当前进程内的句柄不可以被子进程继承
		CREATE_NEW_CONSOLE,	//为新进程创建一个新的控制台窗口
		NULL,	//使用本进程的环境变量
		NULL,	//使用本进程的驱动器和目录
		&si,	//父进程传给子进程的一些信息
		&pi	//保存新进程信息的结构
		)) 
	{
		cout <<"Create Fail!"<< endl;
		exit(1);
	}
	else
	{
		GetSystemTime(&time_start);

		printf("Begin Time:%d:%d:%d-%d:%d:%d:%d\n",time_start.wYear,time_start.wMonth,time_start.wDay,time_start.wHour,time_start.wMinute,time_start.wSecond,time_start.wMilliseconds);
		cout <<"Create Success!"<< endl;
	}
	//使用等待函数来等待所创建进程的死亡
	WaitForSingleObject(pi.hProcess, INFINITE);
	
	GetSystemTime(&time_end);
	printf("End Time: %d:%d:%d-%d:%d:%d:%d",time_start.wYear,time_start.wMonth,time_start.wDay,time_end.wHour,time_end.wMinute,time_end.wSecond,time_end.wMilliseconds);
	
	milliseconds = time_end.wMilliseconds - time_start.wMilliseconds;
	seconds = time_end.wSecond - time_start.wSecond;
	minutes = time_end.wMinute - time_start.wMinute;
	hour = time_end.wHour - time_start.wHour;
	day = time_end.wDay - time_start.wDay;
	month = time_end.wMonth - time_start.wMonth;
	year = time_end.wYear - time_start.wYear;
	if (milliseconds < 0)
	{
		seconds--;
		milliseconds += 1000;
	}
	if (seconds < 0)
	{
		minutes--;
		seconds += 60;
	}
	if (minutes < 0)
	{
		hour--;
		minutes += 60;
	}
	if (hour < 0)
	{
		day--;
		hour += 24;
	}
	if (day < 0)
	{
		month--;
		day += 30;
	}
	if (month < 0)
	{
		year--;
		month += 12;
	}
	printf("\nThis program running time is: ");
	if (year > 0)
	{
		printf("%dY:",year);
	}
	if (month > 0)
	{
		printf("%dM:", month);
	}
	if (day > 0)
	{
		printf("%dD:", day);
	}
	if (hour > 0)
	{
		printf("%dH:", hour);
	}
	if (minutes > 0)
	{
		printf("%dm:", minutes);
	}
	if (seconds > 0)
	{
		printf("%ds:", seconds);
	}
	if (milliseconds > 0)
	{
		printf("%dms", milliseconds);
	}
	printf("\n");
	return 0;
}
           

Linux版本

/********************************************/
/*名称:mytime.c
/*描述:用命令行的形式建立一个新的进程,并保存其运行的时间 
/*作者:野狼
/*日期:2017-03-19
/********************************************/
#include<math.h>
#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>

int main(int argc, char **argv)
{
	//调用系统时间
	struct timeval time_start;
	struct timeval time_end;
	//用以记录进程运行的时间
	float time_use = 0;
	pid_t pid;
	pid = fork();
	if (pid < 0)	//如果出错
	{
		printf("Create Fail!");
		exit(0);
	}
	else if (pid == 0)	//如果是子进程
	{
		printf("Create Child\n");
		gettimeofday(&time_start,NULL);
		printf("111time_start.tv_sec:%d\n",time_start.tv_sec);
		printf("111time_start.tv_usec:%d\n\n",time_start.tv_usec);
		//在子进程中调用execv函数在命令行中来运行一个程序
		execv(argv[1],&argv[1]);
	}
	else
	{	
		gettimeofday(&time_start,NULL);
		printf("time_start.tv_sec:%d\n",time_start.tv_sec);
		printf("time_start.tv_usec:%d\n\n",time_start.tv_usec);
		wait(NULL);	//等待子进程结束
		gettimeofday(&time_end,NULL);
		printf("time_end.tv_sec:%d\n",time_end.tv_sec);
		printf("time_end.tv_usec:%d\n",time_end.tv_usec);
		time_use = (time_end.tv_sec - time_start.tv_sec)*1000000 + (time_end.tv_usec - time_start.tv_usec);
		printf("此程序运行的时间为:%lf微秒",time_use);
	}
	return 0;
}
           

继续阅读