C中子进程的内存使用
Memory usage of child process in C
我读了 article 关于用 C 计算内存使用量的文章,但遇到了问题。
我写了一个简单的测试程序,可以工作一秒以上,使用超过 1 KB 的内存。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a;
int f[1000000];
sleep(1);
scanf("%d",&a);
printf("%d %d\n",a/10,a%10);
return 0;
}
然后我将它编译成一些main.exe
并检查文章
中的程序操作
pid = fork();
if (pid == 0)
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = TIME_LIMIT;
setrlimit(RLIMIT_CPU, &rlim);
execv("./main.exe",NULL);
}
else
{
struct rusage resource_usage;
// set arbitrary lower limit value of memory used
int memory_used = 128;
pid_t pid2;
do {
memory_used = max(memory_used, get_memory_usage(pid));
if ((memory_used > memory_limit)
kill(pid, SIGKILL);
// wait for the child process to change state
pid2 = wait4(pid, &status, WUNTRACED | WCONTINUED, &resource_usage);
} while (pid2 == 0);
}
以及文章
中的函数get_memory_usage()
int get_memory_usage(pid_t pid) {
int fd, data, stack;
char buf[4096], status_child[NAME_MAX];
char *vm;
sprintf(status_child, "/proc/%d/status", pid);
if ((fd = open(status_child, O_RDONLY)) < 0)
return -1;
read(fd, buf, 4095);
buf[4095] = '[=12=]';
close(fd);
data = stack = 0;
vm = strstr(buf, "VmData:");
if (vm) {
sscanf(vm, "%*s %d", &data);
}
vm = strstr(buf, "VmStk:");
if (vm) {
sscanf(vm, "%*s %d", &stack);
}
return data + stack;
}
但问题出在字符串中,其中pid2 = wait4(pid, &status, WUNTRACED | WCONTINUED, &resource_usage);
。 while
只进行一次迭代并等待流程结束。但是我需要计算内存,rusage resource_usage
不给我这个信息。当子进程为 运行 并在他停止的地方停止时,我怎样才能使 while
工作。
当他 ZOMBIE 时,子进程的状态有更多问题。它不提供记忆。我也需要抓住它。因为如果我的 main.exe
我使用这个测试程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a;
int f[1000000];
sleep(1);
scanf("%d",&a);
printf("%d %d\n",a/10,a%10);
return 0;
}
当我在无限 while
中从 get_memory_usage
做一些输出时,它会显示所有 /proc/[pid]/status
输出。我明白了,那个子进程是
Name: check.exe
State: R (running)
之后会
Name: main.exe
State: Z (zombie)
这意味着 proc
无法捕获 main.exe 为 运行 的信息。
根据 waitpid() 手册页,您对 wait4()
的调用会阻塞,直到进程停止,或在停止后再次恢复。这与阻塞等待输入不同,它意味着它已被信号停止(SIGSTOP
)。
您需要的是 WNOHANG
,它可以阻止您的 wait4()
阻塞并使其立即 return,可以证明是这样的:
do
{
// All the stuff you want to do
pid2 = wait4(pid, &status, WNOHANG, &resource_usage);
} while (pid2 == 0);
注意上面的我根本没有测试过,甚至没有编译过。
我读了 article 关于用 C 计算内存使用量的文章,但遇到了问题。
我写了一个简单的测试程序,可以工作一秒以上,使用超过 1 KB 的内存。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a;
int f[1000000];
sleep(1);
scanf("%d",&a);
printf("%d %d\n",a/10,a%10);
return 0;
}
然后我将它编译成一些main.exe
并检查文章
pid = fork();
if (pid == 0)
{
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = TIME_LIMIT;
setrlimit(RLIMIT_CPU, &rlim);
execv("./main.exe",NULL);
}
else
{
struct rusage resource_usage;
// set arbitrary lower limit value of memory used
int memory_used = 128;
pid_t pid2;
do {
memory_used = max(memory_used, get_memory_usage(pid));
if ((memory_used > memory_limit)
kill(pid, SIGKILL);
// wait for the child process to change state
pid2 = wait4(pid, &status, WUNTRACED | WCONTINUED, &resource_usage);
} while (pid2 == 0);
}
以及文章
中的函数get_memory_usage()
int get_memory_usage(pid_t pid) {
int fd, data, stack;
char buf[4096], status_child[NAME_MAX];
char *vm;
sprintf(status_child, "/proc/%d/status", pid);
if ((fd = open(status_child, O_RDONLY)) < 0)
return -1;
read(fd, buf, 4095);
buf[4095] = '[=12=]';
close(fd);
data = stack = 0;
vm = strstr(buf, "VmData:");
if (vm) {
sscanf(vm, "%*s %d", &data);
}
vm = strstr(buf, "VmStk:");
if (vm) {
sscanf(vm, "%*s %d", &stack);
}
return data + stack;
}
但问题出在字符串中,其中pid2 = wait4(pid, &status, WUNTRACED | WCONTINUED, &resource_usage);
。 while
只进行一次迭代并等待流程结束。但是我需要计算内存,rusage resource_usage
不给我这个信息。当子进程为 运行 并在他停止的地方停止时,我怎样才能使 while
工作。
当他 ZOMBIE 时,子进程的状态有更多问题。它不提供记忆。我也需要抓住它。因为如果我的 main.exe
我使用这个测试程序:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int a;
int f[1000000];
sleep(1);
scanf("%d",&a);
printf("%d %d\n",a/10,a%10);
return 0;
}
当我在无限 while
中从 get_memory_usage
做一些输出时,它会显示所有 /proc/[pid]/status
输出。我明白了,那个子进程是
Name: check.exe
State: R (running)
之后会
Name: main.exe
State: Z (zombie)
这意味着 proc
无法捕获 main.exe 为 运行 的信息。
根据 waitpid() 手册页,您对 wait4()
的调用会阻塞,直到进程停止,或在停止后再次恢复。这与阻塞等待输入不同,它意味着它已被信号停止(SIGSTOP
)。
您需要的是 WNOHANG
,它可以阻止您的 wait4()
阻塞并使其立即 return,可以证明是这样的:
do
{
// All the stuff you want to do
pid2 = wait4(pid, &status, WNOHANG, &resource_usage);
} while (pid2 == 0);
注意上面的我根本没有测试过,甚至没有编译过。