- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
首先让我说这里有很多问题。
我论文的其中一项任务要求我编写一个程序来执行一个子程序,如果它的运行时间(不是 wall-time 而是 user+sys )超过特定值或者它的 RAM 消耗是超过另一个指定值。
虽然我还没有弄清楚RAM部分。我用 setitmer 和 ITIMER_PROF 信号消磨时间。 (因为 ITIMER_PROF 收集实际的 CPU 使用率,而不是设置一个时间起点,然后计算 x 时间量)
我使用 setitimer 的原因是我需要的精度低于秒级。 (例如,在 1.75 秒(1750000 微秒)后终止进程。setrlimit 方法只有一秒。
问题 1 为什么在父进程中设置带有 ITIME_PROF 的 setitimer 不工作? child 的 CPU/系统调用不是由它收集的吗?
childPID = fork();
if (childPID == -1){
printf( "Puff paff ... fork() did not work !\n" );
exit(1);
}
// Child
if(childPID == 0) {
execvp(args[0], args);
exit(1);
}
// Parent
else{
// Using a ITIMER_PROF inside the parent program will not work!
// The child may take 1 hour to execute and the parent will wait it out!
// To fix this we need to use a ITIMER_REAL ( wall-time ) but that's not an accurate measurement
struct itimerval timer;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 500000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 500000;
setitimer ( ITIMER_PROF, &timer, NULL);
int status;
waitpid(childPID,&status,0);
if (WIFEXITED(status)) {
fprintf(stderr, "Nice nice, the child exited ... with cPID = %d with status = %d \n", cPID, WEXITSTATUS(status) );
}
}
问题 2 为什么这有效!? execvp 不会覆盖所有函数(timeout_sigprof、main 和任何其他函数)吗?难道就不能有人在子程序中捕捉到信号并取代原来的功能吗?
void timeout_sigprof( int signum ){
fprintf(stderr, "The alarm SIGPROF is here !\nThe actual pid: %d\n", getpid());
//TODO: Write output and say the child terminated with
// ram or time limit exceeded
exit(105); // Note the 105 !
}
childPID = fork();
if (childPID == -1){
printf( "Puff paff ... fork() did not work !\n" );
exit(1);
}
// Child
if(childPID == 0) {
//
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timeout_sigprof;
sigaction (SIGPROF, &sa, NULL);
struct itimerval timer;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 250000;
setitimer ( ITIMER_PROF, &timer, NULL);
execvp(args[0], args);
exit(1);
}
// Parent process
else {
// Waiting for the child
int status;
waitpid(childPID,&status,0);
if (WIFEXITED(status)) {
fprintf(stderr, "Nice nice, the child exited ... with cPID = %d with status = %d \n", cPID, WEXITSTATUS(status) );
}
exit(0);
}
问题 3 为什么放在这里的 dup2 真的可以工作,让 child 的输入/输出被重定向?
childPID = fork();
if (childPID == -1){
printf( "Puff paff ... fork() did not work !\n" );
exit(1);
}
// Child
if(childPID == 0) {
// Redirect all I/O to/from a file
int outFileId = open("output", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
// Redirect the output for the CHILD program. Still don't know why it works.
dup2(outFileId, 1)
// No idea why these dup2's work ! As i close the file descriptors here ?!
close(outFileId);
execvp(args[0], args);
exit(1);
}
// Parent process
else {
// Waiting for the child
int status;
waitpid(childPID,&status,0);
if (WIFEXITED(status)) {
fprintf(stderr, "Nice nice, the child exited ... with cPID = %d with status = %d \n", cPID, WEXITSTATUS(status) );
}
exit(0);
}
这是我编写的代码,它仅在程序运行了 X 时间 (x = 500ms) 后才运行并终止该程序。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <sys/time.h>
volatile pid_t childPID;
// This function should exist only in the parent! The child show not have it after a exec* acording to :
// The exec() family of functions replaces the current process image with a new process image.
void timeout_sigprof( int signum ){
fprintf(stderr, "The alarm SIGPROF is here !\nThe actual pid: %d\n", getpid());
//TODO: Write output and say the child terminated with a ram or time limit exceeded
exit(105); // Note the 105 !
}
int main(int argc, char *argv[]) {
int cstatus;
pid_t cPID;
char *args[2];
args[0] = "/home/ddanailov/Projects/thesis/programs/prime/prime";
args[1] = NULL; // Indicates the end of arguments.
// Handle the SIGPROF signal in the function time_handler in both the child and
struct sigaction sa;
memset (&sa, 0, sizeof (sa));
sa.sa_handler = &timeout_sigprof;
sigaction (SIGPROF, &sa, NULL);
childPID = fork();
if (childPID == -1){
printf( "Puff paff ... fork() did not work !\n" );
exit(1);
}
// Child
if(childPID == 0) {
struct itimerval timer;
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = 250000;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 250000;
setitimer ( ITIMER_PROF, &timer, NULL);
// Redirect all I/O to/from a file
int outFileId = open("output", O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IRGRP | S_IWGRP | S_IWUSR);
// int inFileId = open("input");
// Redirect the output for the CHILD program. Still don't know why it works.
//dup2(inFileId, 0);
dup2(outFileId, 1);
//dup2(outFileId, 2);
// No idea why these dup2's work ! As i close the file descriptors here ?!
close(outFileId);
close(inFileId);
execvp(args[0], args);
exit(1);
}
// Parent process
else {
// Waiting for the child
int status;
waitpid(childPID,&status,0);
if (WIFEXITED(status)) {
fprintf(stderr, "Nice nice, the child exited ... with cPID = %d with status = %d \n", cPID, WEXITSTATUS(status) );
}
exit(0);
}
return 0;
}
任何帮助/解释将不胜感激!
先谢谢大家
前
最佳答案
Why doesn't the setitimer with ITIME_PROF work when it's set in the parent process ? The CPU / System calls for the child are not collected by it ?
不,他们不是。与 ITIME_PROF 相关的计时器仅在设置了计时器的进程正在执行时递减,或者当系统调用代表它执行时,而不是在子进程正在执行时递减。
这些信号通常由分析工具使用,分析工具包含在您链接到您尝试分析的程序的库中。
但是:您可能不需要将信号发送到父进程。如果您的目标是在程序超过允许的使用量后终止程序,那么让它接收 SIGPROF 并退出(如我对下面 Q2 的回答所示)。然后,在 waitpid
返回并且您检测到程序由于 SIGPROF 退出后,您可以通过调用 times
找出 child 实际使用的时间量。或 getrusage
.
唯一的缺点是子程序可以通过在 SIGPROF 上设置它自己的信号处理程序来破坏这个过程。
Why does this WORK!? Doesn't the execvp overwrite all the functions ( timeout_sigprof, main and any other)? And couldn't someone potentially catch the signal in the child program and supersede the original function ?
事实并非如此,或者至少不是您所想的那样。正如您所说,您在父进程中安装的信号处理程序被 execvp 加载的新图像所取代。
它似乎起作用的原因是如果新程序没有为 SIGPROF 设置信号处理程序,那么当该信号被发送到进程时它将终止。回想一下,任何发送到该进程尚未设置处理程序或明确决定忽略的进程的信号都将导致该进程终止。
如果 execvp 正在执行的程序确实为 SIGPROF 设置了信号处理程序,则它不会终止。
更新
看到你的评论,我想我最好试试你的程序。我在 waitpid 之后的 if 语句中添加了另一个分支,如下所示:
waitpid(childPID,&status,0);
if (WIFEXITED(status)) {
fprintf(stderr, "Nice nice, the child exited ... with cPID = %d with status = %d \n", childPID, WEXITSTATUS(status) );
} else if (WIFSIGNALED(status)) {
fprintf(stderr, "Process pid=%d received signal %d\n",childPID,WTERMSIG(status));
}
当我运行它时,我看到以下内容:
$ ./watcher
Process pid=1045 received signal 27
这证实了我上面所说的。我没有看到字符串“The alarm SIGPROF is here !”打印出来,我确实在 parent 身上看到一个迹象表明 child 被信号 27 杀死,这是 SIGPROF。
我只能想到您会看到信号处理程序执行的一种情况,那就是如果计时器设置得太低以至于它在 execv 实际设法加载新图像之前触发。不过,这看起来不太可能。
另一种可能是您无意中在目标程序中安装了相同的信号处理程序(复制粘贴错误?)。
Why does the dup2 placed here actually work and let's the child's input / output to be redirected ?
根据代码中的注释,我假设您的意思是“即使我在 dup2 之后立即关闭了原始文件描述符,为什么它仍然有效?”
dup2将旧的FD复制到新的FD中,所以执行后:
dup2(outFileId, 1);
您有两个文件描述符引用相同的文件描述:一个包含在变量 outFileId 中,另一个是 FD 1(即标准输出)。另请注意,原始标准输出将被此操作关闭。
文件描述符就像对底层文件描述数据结构的引用,代表打开的文件。调用dup2后,有两个文件描述符指向同一个文件描述。
close
的手册页说:
If fd is the last file descriptor referring to the underlying open file description (see open(2)), the resources associated with the open file description are freed
所以它按它应该的方式工作:你仍然有一个打开的 FD,FD 1 (stdout),新的子进程可以写入它。
关于c - 为什么 setitimer 和 dup2 在 execvp 之后为子进程工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24885081/
我是 Linux 的新手,并且继承了保持我们的单一 Linux 服务器运行的职责。这是我们的SVN服务器,所以比较重要。 原来在我之前维护它的人有一个 cron 任务,当有太多 svnserve 进程
Node 虽然自身存在多个线程,但是运行在 v8 上的 JavaScript 是单线程的。Node 的 child_process 模块用于创建子进程,我们可以通过子进程充分利用 CPU。范例:
Jenkins 有这么多进程处于事件状态是否正常? 我检查了我的设置,我只配置了 2 个“执行者”... htop http://d.pr/i/RZzG+ 最佳答案 您不仅要限制 Master 中的执
我正在尝试在 scala 中运行这样的 bash 命令: cat "example file.txt" | grep abc Scala 有一个特殊的流程管道语法,所以这是我的第一个方法: val f
很难说出这里要问什么。这个问题模棱两可、含糊不清、不完整、过于宽泛或夸夸其谈,无法以目前的形式得到合理的回答。如需帮助澄清此问题以便重新打开,visit the help center . 关闭 1
我需要一些帮助来理解并发编程的基础知识。事实上,我读得越多,就越感到困惑。因此,我理解进程是顺序执行的程序的一个实例,并且它可以由一个或多个线程组成。在单核CPU中,一次只能执行一个线程,而在多核CP
我的问题是在上一次集成测试后服务器进程没有关闭。 在integration.rs中,我有: lazy_static! { static ref SERVER: Arc> = {
我正在使用 Scala scala.sys.process图书馆。 我知道我可以用 ! 捕获退出代码和输出 !!但是如果我想同时捕获两者呢? 我看过这个答案 https://stackoverflow
我正在开发一个C++类(MyClass.cpp),将其编译为动态共享库(MyClass.so)。 同一台Linux计算机上运行的两个不同应用程序将使用此共享库。 它们是两个不同的应用程序。它不是多线程
我在我的 C 程序中使用 recvfrom() 从多个客户端接收 UDP 数据包,这些客户端可以使用自定义用户名登录。一旦他们登录,我希望他们的用户名与唯一的客户端进程配对,这样服务器就可以通过数据包
如何更改程序,以便函数 function_delayed_1 和 function_delayed_2 仅同时执行一次: int main(int argc, char *argv[]) {
考虑这两个程序: //in #define MAX 50 int main(int argc, char* argv[]) { int *count; int fd=shm
请告诉我如何一次打开三个终端,这样我的项目就可以轻松执行,而不必打开三个终端三次然后运行三个exe文件。请问我们如何通过脚本来做到这一点,即打开三个终端并执行三个 exe 文件。 最佳答案 在后台运行
我编写了一个监控服务来跟踪一组进程,并在服务行为异常、内存使用率高、超出 CPU 运行时间等时发出通知。 这在我的本地计算机上运行良好,但我需要它指向远程机器并获取这些机器上的进程信息。 我的方法,在
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?将问题更新为 on-topic对于堆栈溢出。 8年前关闭。 Improve this qu
我有一个允许用户上传文件的应用程序。上传完成后,必须在服务器上完成许多处理步骤(解压、存储、验证等...),因此稍后会在一切完成后通过电子邮件通知用户。 我见过很多示例,其中 System.Compo
这个问题对很多人来说可能听起来很愚蠢,但我想对这个话题有一个清晰的理解。例如:当我们在 linux(ubuntu, x86) 上构建一个 C 程序时,它会在成功编译和链接过程后生成 a.out。 a.
ps -eaf | grep java 命令在这里不是识别进程是否是 java 进程的解决方案,因为执行此命令后我的许多 java 进程未在输出中列出。 最佳答案 简答(希望有人写一个更全面的): 获
我有几个与内核态和用户态的 Windows 进程相关的问题。 如果我有一个 hello world 应用程序和一个暴露新系统调用 foo() 的 hello world 驱动程序,我很好奇在内核模式下
我找不到很多关于 Windows 中不受信任的完整性级别的信息,对此有一些疑问: 是否有不受信任的完整性级别进程可以创建命名对象的地方? (互斥锁、事件等) 不受信任的完整性级别进程是否应该能够打开一
我是一名优秀的程序员,十分优秀!