我一直在尝试编写一个程序,该程序可以在孩子超过一定的运行时间后准确地杀死一个分叉的进程。该过程应从磁盘上的可执行文件产生。我在这里使用linux。让我们甚至不要考虑仅在Windows上派生一个进程的丑陋性(对于必须维护Windows源代码的人,我感到抱歉。)
我当前的解决方案setrlimit
在子进程中使用该函数,然后继续调用execvp
以用可执行文件覆盖子进程。该setrlimit
功能可与一个参数被用于RLIMIT_CPU
在为了限制CPU运行时间的方法。本质上,派生的孩子限制了它自己的运行时间,然后execvp
用于启动可执行文件。
我写了一个proc_timer结构,它存储运行可执行文件所需的信息:
typedef struct _proc_timer {
double limit;
char** args;
char* name;
pid_t proc;
int argc;
} proc_timer;
该结构已通过名为的函数正确分配和初始化make_timer
。但这不是问题。
当前代码如下所示:
int status;
const pid_t proc = fork();
if (proc < 0)
return FORK_FAIL;
else if (proc == 0) {
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = (rlim_t)timer->limit + 1; // An extra second, since rlim_t is in seconds.
if (setrlimit(RLIMIT_CPU, &rlim) < 0)
_exit(TIME_FAILURE);
execvp(timer->name, timer->args);
_exit(NOT_FOUND);
}
timer->proc = proc; // save the PID, probably not useful though.
waitpid(proc, &status, 0); // wait for the child.
// If true, then the termination was caused by an exceeded time limit.
if (WTERMSIG(status) == SIGXCPU) {
fprintf(stderr, "We crossed the time limit!");
}
请注意,在上面的代码中,我必须给子进程多于limit
几秒钟的时间,因为struct rlimit
只能接受type的限制rlim_t
,该限制是整数。现在,如果用户想要一个浮点数,我仍然必须为子进程提供整数秒数。这就是为什么我不得不写:
rlim.rlim_cur = rlim.rlim_max = (rlim_t)timer->limit + 1; // An extra second, since rlim_t is in seconds.
这显然是一个过高的估计,但是我还没有考虑其他可行的选择。
无论如何,以下解决方案将无法正常工作,因为报警器会测量实际时间,而不是CPU时间,这在我编写此问题时并不知道。我只对CPU时间感兴趣。
但是,我已经找到了潜在的解决方案。它涉及在ualarm
调用之前使用系统调用waitpid
。由于ualarm
以微秒为单位的参数,因此比setrlimit
解决方案要准确得多。然后,紧接着waitpid
,我将通过致电来禁用警报ualarm(0, 0)
。这样,如果父母仍在等待孩子并且超过了时间限制,则将发送父母SIGALRM
,我可以处理。但是,此解决方案有很多问题,我永远不会考虑使用它。处理信号的唯一方法是使函数充当处理程序。可以使用sigaction
或直接调用来完成signal
安装处理程序的功能。但是,处理程序只能是一个带有一个参数的函数,这是发送信号的整数,无法让处理程序知道要杀死哪个进程!
解决此问题的唯一方法是设置一个全局变量来存储pid,但这会引起问题,因为此代码将用作GUI应用程序的背景代码,从理论上讲,用户应该能够在其中执行此过程一次多次。为所有不同的过程存储多个全局变量将使这种解决方案无法工作。
因此,这里的最佳解决方案是setrlimit
在孩子中使用该功能。但是,我不能在这里准确使用浮点数!还有另一种更准确的解决方案吗?
忽略我在评论中所说的话:我相信您正在setitimer
使用ITIMER_VIRTUAL
。你会在孩子之前称这个execve
。经过一定的CPU时间后,它可以触发致命信号,其分辨率以毫秒为单位,并且(与timer_create
和不同ualarm
)据记载可以存活execve
。但是请注意,没有什么可以阻止清除计时器本身的过程。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句