首页 > 解决方案 > 我如何生成 n 个子进程以同时运行,测量它们的执行时间并防止它们中的每一个超过最大执行时间?

问题描述

所以我的目标是产生 n 个子进程并让它们同时运行(每个 exec 都是不同的程序)。

棘手的是,对于它们中的每一个,我必须确保它们不超过预定的执行时间。(不是全局的,而是相对于它的开始时间)。

我只有一个生成进程的工作代码,执行每个进程,然后等待所有进程完成。(基于这个答案)。

我尝试过使用SIGALRM,但我不知道如何设置一个警报,fork因此它会超时每个进程相对于其开始时间而不是基于父级的开始时间。

关于时间测量,我不确定如何获得每个分叉的执行时间。

在一般情况下,我只会在子代码中获取开始和结束时间的增量,但在这种情况下,如果我没记错的话,它们都会执行一些操作,所以我会丢失对以下代码的任何引用。

for (int j = 0; j < prog_count; j++) {
            pid_t monitor_pid = fork();
            if(monitor_pid==0){
                execvp(programs[j]->executable, programs[j]->exec_args);
            }

    }
while ((wpid = wait(&status)) > 0);

我见过很多例子,它们产生一个孩子并通过并行运行的睡眠定时器进程控制它的执行时间,但我不知道如何将该解决方案扩展到我的情况。

标签: cconcurrencysignalsfork

解决方案


人警报

应用程序使用

[...] exec 函数之一创建的新进程映像继承了旧进程映像中警报信号的剩余时间。

因此,您可以尝试编写如下内容:

#define LIMIT_TIME_SEC 10

for (int j = 0; j < prog_count; j++) {
    pid_t monitor_pid = fork();
    if(monitor_pid==0){
        alarm(LIMIT_TIME_SEC);
        execvp(programs[j]->executable, programs[j]->exec_args);
    }

}
while ((wpid = wait(&status)) > 0);

在此代码中,该alarm函数在之后调用,fork因此它仅影响子进程。当到达指示的时间时alarm,将SIGALARM发送到由exec函数启动的进程,如果它不处理信号,它将终止它。


如果每个子程序有不同的超时时间,你可以用LIMIT_TIME_SEC一些像数组一样索引的数组来替换programs


如果你想知道子进程执行了多少时间,你可以构建这样的东西:

  • 记录孩子pid在程序中struct添加必要的成员(pid_t pid;
  • 记录孩子启动的时间,从父级,添加成员(time_t launch_time;

for (int j = 0; j < prog_count; j++) {
    pid_t monitor_pid = fork();
    
    if (monitor_pid==0)
    {
        /** in child **/
        /* set a limit time of execution */
        alarm(LIMIT_TIME_SEC);
        /* execute the program */
        execvp(programs[j]->executable, programs[j]->exec_args);
    }
    else
    {
        /** in parent **/
        /* record the starting time */
        programs[j]->launch_time = time(NULL);
        
        /* record the pid */
        programs[j]->pid = monitor_pid;
    }

}
while ((wpid = wait(&status)) > 0)
{
    /* a child terminates, let's find it */
    for (int j = 0; j < prog_count; ++tj)
    {
        if (programs[j]->pid == wpid)
        {
            /* print process information */
            printf("program %s terminated in %df seconds\n",
                    programs[j]->executable,
                    difftime(time(NULL) - programs[j]->launch_time));

            /* process found, not necessary to go further */
            break;
        }
    }
}

推荐阅读