分页: 1 / 1
对于fork()的疑问
发表于 : 2009-05-12 11:06
由 lonelycorn
fork()的返回值
-1:失败
0:这是子进程
>0:这是父进程,返回值是子进程的pid
现在我写了一个程序,fork()成两个线程,子进程execv了一个"test"的小程序,父进程去监控子进程的运行情况(内存、信号,等等)具体来说就是cat /proc/<pid>/stat。
但是现在出现了一个问题,fork()后返回给父进程的pid好像有时候是父进程的pid,而不是子进程的pid
比如,我期待的输出是
代码: 全选
pid is 5861,pid_string is 5861
5861 (test) R 5860 5860 4200 34816 5860 4202496 55 0 0 0 18 0 0 0 20 0 1 0 342997 40214528 18 4294967295 134512640 134608672 3218846416 3218846408 134512790 0 0 0 1224 0 0 0 17 1 0 0 0 0 0
40214528.18
vmsize=39272,vmrss=72
5861 (test) R 5860 5860 4200 34816 5860 4202496 55 0 0 0 18 0 0 0 20 0 1 0 342997 40214528 18 4294967295 134512640 134608672 3218846416 3218846408 134512780 256 0 0 1224 0 0 0 17 1 0 0 0 0 0
0.0
vmsize=0,vmrss=0
也就是显示我execv的test的运行情况,但是有1/10的概率出现下面的结果:
代码: 全选
pid is 5868,pid_string is 5868
5868 (tmp) R 5867 5867 4200 34816 5867 4202560 0 0 0 0 0 0 0 0 20 0 1 0 343116 2899968 26 4294967295 134512640 134521899 3217852880 3217852544 3087717424 0 0 0 0 0 0 0 17 0 0 0 0 0 0
2899968.56
vmsize=2832,vmrss=224
5868 (tmp) R 5867 5867 4200 34816 5867 4202560 37 0 0 0 0 0 0 0 20 0 1 0 343116 4096 1 4294967295 0 0 0 3217852576 3087717424 256 0 0 0 0 0 0 17 0 0 0 0 0 0
0.0
vmsize=0,vmrss=0
显示的是父进程(我的程序编译后叫tmp)的状况。
请问这是为什么?是不是我检测到的是还没有执行execv的子进程?
thx in advance
Re: 对于fork()的疑问
发表于 : 2009-05-12 11:15
由 taylor
看不懂你贴的是什么,code呢
Re: 对于fork()的疑问
发表于 : 2009-05-14 21:49
由 lonelycorn
上代码了
代码: 全选
#include <iostream>
#include <fstream>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
const double DELTA = 1.0;
const int TIME = 100;
const int MEM = 18192;
const int OFFSET = 10;
using namespace std;
char *pid_to_string(int pid)
{
char s[50];
sprintf(s,"%d",pid);
char *s1=s;
return s1;
}
int pid_to_string(int pid,char *s)
{
sprintf(s,"%d",pid);
return 0;
}
long get_memory(int pages)
{
long factor = 0;
factor = (long)sysconf(_SC_PAGESIZE);
return pages*factor/1024;
}
void get_timespec(struct timespec *s, int time)
{
s->tv_sec = time / 1000;
s->tv_nsec = (time % 1000 ) * 1000000;
}
/*
return 0 if OK
return 1 if MLE
*/
int check_memory(char *pid_string)
{
using std::ios_base;
using std::ifstream;
using std::string;
double vm_usage = 0.0;
double resident_set = 0.0;
// 'file' stat seems to give the most reliable results
//
char buffer[100];
sprintf(buffer,"/proc/%s/statm",pid_string);
ifstream statm_stream(buffer,ios_base::in);
long vmsize=0;
statm_stream>>vmsize;
vmsize=vmsize*sysconf(_SC_PAGESIZE)/1024;
cerr<<"vmsize is "<<vmsize<<endl;
struct rusage used;
getrusage(RUSAGE_CHILDREN,&used);
cerr<<"memory usage:"<<used.ru_minflt*sysconf(_SC_PAGESIZE)/1024<<endl;
}
int main()
{
srand((unsigned) time(NULL));
pid_t pid=fork();
if ( pid == -1)
{
cerr<<"error while forking"<<endl;
exit(EXIT_FAILURE);
}
else if (pid == 0)
{
struct rlimit limit;
/* time limit */
limit.rlim_cur=limit.rlim_max=1;
setrlimit(RLIMIT_CPU,&limit);
/* memory limit */
limit.rlim_cur=limit.rlim_max=MEM * 1024;
setrlimit(RLIMIT_AS,&limit);
char *argv[]={(char *)"test",(char *)NULL};
execv(argv[0],argv);
cerr<<"failed to execv"<<endl;
exit(5);
}
else if (pid > 0)
{
int status,tmp,left_t;
struct timespec spec;
char pid_string[20];
pid_to_string(pid,pid_string);
get_timespec(&spec,OFFSET);
left_t = TIME;
while (1)
{
tmp = waitpid(pid,&status,WNOHANG);
if (tmp!=0) break;
/* check resource usage */
if ( (rand() % 100) < 100)
{
tmp = check_memory(pid_string);
if (tmp>0)
{
switch (tmp)
{
case 1 :cerr<<"time limit exceeded"<<endl;break;
case 2 :cerr<<"memory limit exceeded"<<endl;break;
}
kill(pid,SIGKILL);
break;
}
}
nanosleep(&spec,NULL);
left_t -= OFFSET;
if (left_t<=0)break;
}
tmp = check_memory(pid_string);
struct rusage used;
getrusage(RUSAGE_CHILDREN,&used);
printf("ru_maxrss:%ld\n",used.ru_maxrss);
printf("ru_ixrss:%ld\n",used.ru_ixrss);
printf("ru_idrss:%ld\n",used.ru_idrss);
printf("ru_isrss:%ld\n",used.ru_isrss);
printf("ru_minflt:%ld\n",used.ru_minflt);
printf("ru_majflt:%ld\n",used.ru_majflt);
printf("ru_nswap:%ld\n",used.ru_nswap);
printf("ru_inblock:%ld\n",used.ru_inblock);
printf("ru_oublock:%ld\n",used.ru_oublock);
cerr<<"memory usage:"<<used.ru_minflt*sysconf(_SC_PAGESIZE)/1024<<endl;
tmp = waitpid(pid,&status,WNOHANG);
if (tmp == 0)
{
kill(pid,SIGKILL);
cerr<<"time limit exceeded,killed"<<endl;
}
if (WIFEXITED(status))
{
cerr<<"child thread exit normally"<<endl;
cerr<<"child thread exit status is "<<WEXITSTATUS(status)<<endl;
}
else
{
cerr<<"child thread exit abnormally"<<endl;
if (WIFSIGNALED(status))
{
switch (WTERMSIG(status))
{
case SIGXCPU:cerr<<"SIGXCPU:time limit exceeded"<<endl; break;
case SIGXFSZ:cerr<<"SIGXFSZ:file size exceeded"<<endl; break;
case SIGSEGV:cerr<<"SIGSEGV:segmentation fault"<<endl; break;
default:cerr<<"caught signal "<<WTERMSIG(status)<<endl; break;
}
}
cerr<<"child thread exit status is "<<WEXITSTATUS(status)<<endl;
}
exit(EXIT_SUCCESS);
}
}
Re: 对于fork()的疑问
发表于 : 2009-05-14 21:50
由 lonelycorn
中间废话多了点,但是大体内容就是fork()后检查/proc/pid/statm
Re: 对于fork()的疑问
发表于 : 2009-05-14 22:35
由 peachcolor
好长啊,木有耐心
Re: 对于fork()的疑问
发表于 : 2009-05-15 21:29
由 lonelycorn
OK,Let's精简
代码: 全选
#include <iostream>
#include <fstream>
#include <sys/wait.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
const double DELTA = 1.0;
const int TIME = 100;
const int MEM = 18192;
const int OFFSET = 10;
using namespace std;
/*
将时间转换为struct timespec格式
*/
void get_timespec(struct timespec *s, int time)
{
s->tv_sec = time / 1000;
s->tv_nsec = (time % 1000 ) * 1000000;
}
/*
return 0 if OK
return 1 if MLE
从/proc/pid/stat读入内存信息
*/
int check_memory(int pid)
{
using std::ios_base;
using std::ifstream;
using std::string;
double vm_usage = 0.0;
double resident_set = 0.0;
// 'file' stat seems to give the most reliable results
//
char buffer[100];
sprintf(buffer,"/proc/%d/statm",pid);
ifstream statm_stream(buffer,ios_base::in);
long vmsize=0;
statm_stream>>vmsize;
vmsize=vmsize*sysconf(_SC_PAGESIZE)/1024;
cerr<<"vmsize is "<<vmsize<<endl;
struct rusage used;
getrusage(RUSAGE_CHILDREN,&used);
cerr<<"memory usage:"<<used.ru_minflt*sysconf(_SC_PAGESIZE)/1024<<endl;
}
int main()
{
srand((unsigned) time(NULL));
pid_t pid=fork();
if (pid == 0)
{
/* 子进程,设置一些限制,然后execv() */
struct rlimit limit;
/* time limit */
limit.rlim_cur=limit.rlim_max=1;
setrlimit(RLIMIT_CPU,&limit);
/* memory limit */
limit.rlim_cur=limit.rlim_max=MEM * 1024;
setrlimit(RLIMIT_AS,&limit);
char *argv[]={(char *)"test",(char *)NULL};
execv(argv[0],argv);
}
else if (pid > 0)
{
/* 父进程,监视子进程的内存*/
int status,tmp,left_t;
struct timespec spec;
get_timespec(&spec,OFFSET);
left_t = TIME;
while (1)
{
tmp = waitpid(pid,&status,WNOHANG);
if (tmp!=0) break;
/* check resource usage */
tmp = check_memory(pid);
if (tmp>0)
{
switch (tmp)
{
case 1 :cerr<<"time limit exceeded"<<endl;break;
case 2 :cerr<<"memory limit exceeded"<<endl;break;
}
kill(pid,SIGKILL);
break;
}
nanosleep(&spec,NULL);
left_t -= OFFSET;
if (left_t<=0)break;
}
}
}