Operating|进程控制


一、实验目的
设计并实现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所示
Operating|进程控制
文章图片

图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所示):
Operating|进程控制
文章图片


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

图3
(3)GoBang这个子进程被关闭以后的截图如下(图4):
Operating|进程控制
文章图片

图4
2、Linux环境下的实验结果 (1)、mytime.c编译后的截图(图5所示)
Operating|进程控制
文章图片

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

图6
六、实验分析与总结 1、在Windows、Linux系统下,分别调用相应的API函数对进程进行创建、同步和获取并记录进程运行的时间,正确利用可执行文件来实现命令行创建进程。这次实验不论是linux还是windows,主要思路只有一个: 利用fork()或者createprocess()函数建立一个子进程,在建立成功之后记录运行时间,然后利用wait()或者waitforsingleobject()函数等待子进程的同步,之后再记录运行时间,用两次时间相减就可以。
2、注意的地方是,windows下的计时函数GetSystemTime()不太好用了,函数返回的是系统的时间,要用两次时间相减,这里要注意可能有负数的情况,所以要考虑借位,其实windows下面有一个好用的函数clock(),这个函数对于计时很在行。
【Operating|进程控制】3、收获:加深了对一些API函数的理解和应用。

七.实验源代码 Windows版本

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




    推荐阅读