进程控制
来源:互联网 发布:阿里云 驾照识别 编辑:程序博客网 时间: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函数的理解和应用。
七.实验源代码
/*题目要求:设计并实现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;}
/********************************************//*名称: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;}
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制
- 进程控制 .
- 进程控制
- Codeforces Round #416 (Div. 2) A. Vladik and Courtesy
- 8年暴涨273万倍 比特币的前世今生
- hibernate5快速入门
- 多态详解
- Java中的自动装箱与拆箱
- 进程控制
- [杂题] Codeforces 739D Round #381 (Div. 1) D. Recover a functional graph
- WinRT surface屏幕常亮设置
- NYOJ 58最少步数
- • 实战案例:科技工作者心理健康数据分析
- [一天几个linux命令] 用户与用户组
- 计算机图形学-基于OpenGL的绘制直线及图形变换练习
- 判断是否是合法的出栈序列
- 勒索病毒刷出的存在感远不及安全公司强!