OS_exp2 进程控制(Linux环境)

这篇博客介绍了如何在Linux环境下设计和实现Unix的`time`命令,名为`mytime`。该命令创建子进程运行指定程序,并记录程序运行时间。内容涵盖`fork()`、`execv()`、`wait()`、`gettimeofday()`等函数的使用,以及如何处理命令行参数,包括无时间参数和带有时间参数的情况。文章提供了详细代码和执行流程分析。
摘要由CSDN通过智能技术生成

注:此博客不再更新,所有最新文章将发表在个人独立博客limengting.site。分享技术,记录生活,欢迎大家关注

【实验二】实验要求

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

在Windows下实现:

使用CreateProcess()来创建进程
使用WaitForSingleObject()在“mytime”命令和新创建的进程之间同步
调用GetSystemTime()来获取时间

在Linux下实现:

使用fork()/vfork /exec()来创建进程运行程序
使用wait()等待新创建的进程结束
调用gettimeofday()来获取时间

mytime的用法:
$ mytime.exe program1

要求输出程序program1运行的时间

$ mytime.exe program2 t

t为时间参数,为program2的输入参数,控制program2的运行时间。最后输出program2的运行时间,应和t基本接近。

显示结果: ××小时××分××秒××毫秒××微秒

1.1~1.8为函数介绍和踩坑分析等废话,想看代码和运行结果请直接划到文末1.9查看。

一、Linux环境下

1.0 程序设计思路

(1)创建子进程之前,先创建time_start和time_end结构体,
struct timeval time_start;
struct timeval time_end;
(2)用fork()函数创建进程,通过返回值来判断是子进程还是父进程。
if (fork() == 0) //子进程
else if (fork() >= 0) //父进程
(3)① 如果第(2)步中是子进程运行,记录子进程开始运行的时间,并在子进程中调用execv()函数,execv()函数从终端传入的参数argv[1]中得知可执行文件的文件名并执行:execv(argv[1],&argv[1])
② 如果第(2)步是父进程在运行,记录(fork后)父进程开始运行的时间gettimeofday(&time_start,NULL);。
如果在终端中是不带时间参数的mytime命令调用,即argc == 2,则先调用wait()等待子进程运行结束,然后再获取进程终止的时间gettimeofday(&time_end,NULL);;如果在终端中是带时间参数的mytime命令调用,即argc == 3,则利用atof()函数将argv[2]中的char*型数据转换为double型数据,父进程调用usleep(sleep_sec * 1000000)函数等待子进程运行sleep_sec秒(即sleep_sec * 1000000微秒)后kill掉子进程,并获取程序终止的时间gettimeofday(&time_end,NULL);
(4)计算程序运行的时间(微秒)并将其转换成××小时××分××秒××毫秒××微秒的格式:
time_use = (time_end.tv_sec - time_start.tv_sec) * 1000000 + (time_end.tv_usec - time_start.tv_usec);
time_hour = time_use / (60 * 60 * 1000 * 1000);
time_left = time_use % (60 * 60 * 1000 * 1000);
time_min = time_left / (60 * 1000 * 1000);
time_left %= (60 * 1000 * 1000);
time_sec = time_left / (1000 * 1000);
time_left %= (1000 * 1000);
time_ms = time_left / 1000;
time_left %= 1000;
time_us = time_left;
(5)输出程序运行的时间:
printf(“此程序运行的时间为:%ld 小时, %ld 分钟, %ld 秒, %ld 毫秒, %ld 微秒\n”,time_hour, time_min, time_sec, time_ms, time_us);
(6)将c文件编译链接为可执行文件:
gcc exp2_linux.c –o exp2_linux.o
(7)修改.bashrc文件,将exp2_linux.o封装成mytime命令,并用source .bashrc命令使配置生效。
(8)在终端执行mytime program1统计program1的运行时间并输出或者执行mytime program2 t规定program2的执行时间大约为t,运行program2并输出与规定的t差不多的运行时间。

1.1 getpid()和getppid()

getpid()得到本身进程id,getppid()得到父进程进程id,如果已经是父进程,得到系统进程id,如bash环境运行得到bash的id

1.2 fork()

fork()为创建子进程,有三种不同的返回值:

1、在父进程中,fork返回新创建的子进程的PID

2.、在子进程中,fork返回0

3、如果出现错误,fork返回一个负值

另外在子进程被创建之前,只有一个进程在运行,但在fork创建子进程后,两进程同时运行

程序示例:

int main()
{
    pid_t pid;
    printf("Before fork ...\n");

    switch(pid = fork())
    {
        case -1:
            printf("Fork call fail\n");
            exit(1);

        case 0:
            printf("The pid of child is: %d\n", getpid());
            printf("The pid of child's parent is: %d\n", getppid());
            printf("Child exiting...\n");
            exit(0);

        default:
            printf("The pid of parent is: %d\n", getpid());
            printf("the pid of parent's child is: %d\n", pid);
    }
    printf("After fork, program exiting...\n");
    exit(0);
}

输出:

/home/sunnie/CLionProjects/OS_exp2/cmake-build-debug/OS_exp2
Before fork ...
The pid of parent is: 11731
the pid of parent's child is: 11732
After fork, program exiting...
The pid of child is: 11732
The pid of child's parent is: 1
Child exiting...

Process finished with exit code 0

1.3 execv()

1、函数原型

int execv(const char *progname, char *const argv[]);   // #include <unistd.h>

2、用法介绍

execv会停止执行当前的进程,并且以progname应用进程替换被停止执行的进程,进程ID没有改变。

progname: 被执行的应用程序。

argv: 传递给应用程序的参数列表, 注意,这个数组的第一个参数应该是应用程序名字本身,并且最后一个参数应该为NULL,不参将多个参数合并为一个参数放入数组。

3、返回值

如果应用程序正常执行完毕,那么execv是永远不会返

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值