我怎样才能同时生成 n 个子进程 运行,测量它们的执行时间并防止它们中的每一个都超过最大执行时间?

How can i spawn n child processes to run concurrently, measure their execution time and prevent each one of them of exceeding a max execution time?

所以我的 objective 是生成 n 个子进程并让它们 运行 并发(每个 exec 是一个不同的程序)。

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

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

我试过使用 SIGALRM,但我不知道如何为每个 fork 设置一个警报,所以它确实会根据其开始时间而不是基于父进程的开始时间来超时每个进程开始时间。

关于时间测量,我不确定如何获得每个 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);

我见过很多示例,这些示例生成一个子节点并通过并行 运行s 的休眠计时器进程控制其执行时间,但我无法弄清楚如何将该解决方案扩展到我的情况。

来自 man alarm

Application Usage

[...] A new process image created by one of the exec functions inherits the time left to an alarm signal in the old process' image.

所以你可以尝试这样写:

#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 之后被调用 ,因此它仅影响 child 进程。当到达 alarm 指示的时间时,SIGALARM 被发送到由 exec 函数启动的进程,如果它不处理信号,它将终止它。


如果每个 sub-program 都有不同的超时时间,您可以用一些像 programs 数组这样索引的数组替换 LIMIT_TIME_SEC


如果您想知道 child 个进程执行了多少时间,您可以构建类似的东西:

  • 在程序中记录childpidstruct添加必要的成员(pid_t pid;)
  • 记录child上线的时间,从parent,添加成员(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;
        }
    }
}