天天看點

程序控制一、實驗目的二、實驗内容三、實驗環境四、實驗方法與步驟五、實驗結果六、實驗分析與總結七.實驗源代碼

一、實驗目的

設計并實作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;
}
           

繼續閱讀