进程控制

来源:互联网 发布:阿里云 驾照识别 编辑:程序博客网 时间:2024/06/08 15:51

一、实验目的

设计并实现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;}