我如何从PROC获取有关子进程的信息
我正在尝试编写一个程序,该程序需要几个进程作为参数。然后,父进程执行每个子进程,并打印出有关该子进程的一些统计信息。
示例:/ generate ls -l //将导致程序打印出一些有关ls的统计信息- l(特别是它的系统时间,用户时间和上下文切换次数)。
I am trying to write a program that takes a few processes as its arguments. Then the parent process executes each child process and prints out a few statistics with regard to the same.
Example: /generate ls -l //Would result in a program that prints out some statistics with regard to ls -l (Specifically its system time, user time and number of context switches).
我想从Proc文件系统中获取必要的信息,而不是使用getrusage()函数。现在,我的理解是,如果我要使用wait()函数,它将最终从proc文件系统中删除信息。我在下面包含了我的代码
Instead of using the getrusage() function, I would like to get the necessary information from the Proc file system. Now my understanding is that if I were to use a wait() function, it would end up removing the information from my proc file system. I have included my code below
#include <time.h>
#include <stdbool.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/resource.h>
void inputted_command(int a, char **b){
for(int i=1;i<a;i++)
printf("%s ",b[i]);
}
int main(int argc, char **argv){
int status;
pid_t childpid;
pid_t get_information;
if (argc < 2)
{
return 1;
}
bool handle_signals = (signal(SIGINT, SIG_IGN) != SIG_IGN);
clock_t t;
t= clock();
pid_t pid = fork();
if(pid<0)
{
printf("fork: error no = %s\n",strerror(errno));
return 1;
}
else if(pid>0){
signal(SIGINT,SIG_IGN);
sleep(60);
/*
get_information=fork();
if(get_information==0){
execlp(___);
}else
waitpid(pid, &status, 0);
*/
waitpid(childpid, &status, 0);
t= clock()-t;
double real_time_taken = ((double)t)/CLOCKS_PER_SEC;
printf("The command ");
inputted_command(argc,argv);
if(WIFSIGNALED(status)){
printf("is interrupted by the signal number = %d (Insert Name Here) real: %.2f, user: , system: , context switch: \n",WTERMSIG(status),real_time_taken);
}
else{
printf("terminated with return status code = %d real: %.2f, user: , system: , context switch: \n",WEXITSTATUS(status), real_time_taken);
}
}
else if(pid==0){
childpid=getpid();
printf("Process with id: %d created for the command: ",(int)getpid());
inputted_command(argc,argv);
printf("\n");
assert(pid == 0);
if (handle_signals)
signal(SIGINT, SIG_DFL);
execvp(argv[1], &argv[1]);
printf(" experienced an error in starting the command: ");
inputted_command(argc,argv);
printf("\n");
exit(-1);
}
}
- 我的部分代码已被注释,我不确定该怎么做。
- 我的想法是首先让父进程进入睡眠状态,以便子进程完成
- 然后,父进程创建一个新的子进程,以访问PROC / Fie系统并获取必要的数据(已被注释)。
- 最后,我称等待再次运行并终止初始子进程
所以我在这里的主要问题是,这是否是获取子进程信息的适当方式,以及如何获取信息(主要是系统时间,用户时间以及自愿和非自愿上下文切换?
So my main question here is whether this would be an appropriate way to go about getting information for the child process and how do I go about getting the information(Mainly the System Time, User Time and the voluntary and involuntary context switches?
这是一个测试程序,我煮熟了,可能会有所启发(注意:有点粗糙):
Here's a test program that I cooked up that may shed some light (Caveat: it is somewhat crude):
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <signal.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
int mode = -1;
pid_t pid;
time_t cur;
FILE *xf;
char dirproc[100];
char dirfd[100];
char status_file[100];
char cmd[100];
void
xsystem(char *cmd)
{
printf("CMD: %s\n",cmd);
system(cmd);
}
int
check(int nmode)
{
struct stat st;
int errst;
int errkill;
char buf[500];
errkill = kill(pid,0);
errst = stat(dirproc,&st);
if (nmode != mode) {
printf("elap=%d errkill=%d errst=%d\n",cur,errkill,errst);
sprintf(cmd,"ls -l /proc/%d",pid);
xsystem(cmd);
sprintf(cmd,"ls -l /proc/%d/fd",pid);
xsystem(cmd);
sprintf(cmd,"cat /proc/%d/status",pid);
xsystem(cmd);
printf("fgets\n");
rewind(xf);
while (1) {
char *cp = fgets(buf,sizeof(buf),xf);
if (cp == NULL)
break;
fputs(buf,stdout);
}
mode = nmode;
}
return errkill;
}
// main -- main program
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
default:
break;
}
}
setlinebuf(stdout);
setlinebuf(stderr);
pid = fork();
if (pid == 0) {
open("/dev/null",O_RDONLY);
sleep(1);
exit(0);
}
sprintf(dirproc,"/proc/%d",pid);
sprintf(dirfd,"/proc/%d/fd",pid);
sprintf(status_file,"/proc/%d/status",pid);
xf = fopen(status_file,"r");
time_t beg = time(NULL);
cur = 0;
while (1) {
cur = time(NULL);
cur -= beg;
if (cur >= 4)
break;
check(1);
}
printf("\n");
printf("postloop\n");
check(2);
waitpid(pid,NULL,0);
printf("\n");
printf("postwait\n");
check(3);
return 0;
}
这是程序输出:
Here is the program output:
elap=0 errkill=0 errst=0
CMD: ls -l /proc/94913
total 0
dr-xr-xr-x. 2 xxx xxx 0 Oct 21 15:50 attr
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 autogroup
-r--------. 1 xxx xxx 0 Oct 21 15:50 auxv
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 cgroup
--w-------. 1 xxx xxx 0 Oct 21 15:50 clear_refs
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 cmdline
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 comm
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 coredump_filter
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 cpuset
lrwxrwxrwx. 1 xxx xxx 0 Oct 21 15:50 cwd -> /tmp/cld
-r--------. 1 xxx xxx 0 Oct 21 15:50 environ
lrwxrwxrwx. 1 xxx xxx 0 Oct 21 15:50 exe -> /tmp/cld/pgm2
dr-x------. 2 xxx xxx 0 Oct 21 15:50 fd
dr-x------. 2 xxx xxx 0 Oct 21 15:50 fdinfo
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 gid_map
-r--------. 1 xxx xxx 0 Oct 21 15:50 io
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 latency
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 limits
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 loginuid
dr-x------. 2 xxx xxx 0 Oct 21 15:50 map_files
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 maps
-rw-------. 1 xxx xxx 0 Oct 21 15:50 mem
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 mountinfo
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 mounts
-r--------. 1 xxx xxx 0 Oct 21 15:50 mountstats
dr-xr-xr-x. 6 xxx xxx 0 Oct 21 15:50 net
dr-x--x--x. 2 xxx xxx 0 Oct 21 15:50 ns
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 numa_maps
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 oom_adj
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 oom_score
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 oom_score_adj
-r--------. 1 xxx xxx 0 Oct 21 15:50 pagemap
-r--------. 1 xxx xxx 0 Oct 21 15:50 personality
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 projid_map
lrwxrwxrwx. 1 xxx xxx 0 Oct 21 15:50 root -> /
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 sched
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 schedstat
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 sessionid
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 setgroups
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 smaps
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 smaps_rollup
-r--------. 1 xxx xxx 0 Oct 21 15:50 stack
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 stat
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 statm
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 status
-r--------. 1 xxx xxx 0 Oct 21 15:50 syscall
dr-xr-xr-x. 3 xxx xxx 0 Oct 21 15:50 task
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 timers
-rw-rw-rw-. 1 xxx xxx 0 Oct 21 15:50 timerslack_ns
-rw-r--r--. 1 xxx xxx 0 Oct 21 15:50 uid_map
-r--r--r--. 1 xxx xxx 0 Oct 21 15:50 wchan
CMD: ls -l /proc/94913/fd
total 0
lrwx------. 1 xxx xxx 64 Oct 21 15:50 0 -> /dev/pts/0
l-wx------. 1 xxx xxx 64 Oct 21 15:50 1 -> /tmp/out2
l-wx------. 1 xxx xxx 64 Oct 21 15:50 2 -> /tmp/out2
lr-x------. 1 xxx xxx 64 Oct 21 15:50 3 -> /dev/null
CMD: cat /proc/94913/status
Name: pgm2
Umask: 0022
State: S (sleeping)
Tgid: 94913
Ngid: 0
Pid: 94913
PPid: 94912
TracerPid: 0
Uid: 500 500 500 500
Gid: 500 500 500 500
FDSize: 64
Groups: 500
NStgid: 94913
NSpid: 94913
NSpgid: 94912
NSsid: 3771
VmPeak: 4136 kB
VmSize: 4136 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 80 kB
VmRSS: 80 kB
RssAnon: 80 kB
RssFile: 0 kB
RssShmem: 0 kB
VmData: 44 kB
VmStk: 132 kB
VmExe: 8 kB
VmLib: 1872 kB
VmPTE: 52 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
Threads: 1
SigQ: 0/47895
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 1
nonvoluntary_ctxt_switches: 0
fgets
Name: pgm2
Umask: 0022
State: S (sleeping)
Tgid: 94913
Ngid: 0
Pid: 94913
PPid: 94912
TracerPid: 0
Uid: 500 500 500 500
Gid: 500 500 500 500
FDSize: 64
Groups: 500
NStgid: 94913
NSpid: 94913
NSpgid: 94912
NSsid: 3771
VmPeak: 4136 kB
VmSize: 4136 kB
VmLck: 0 kB
VmPin: 0 kB
VmHWM: 80 kB
VmRSS: 80 kB
RssAnon: 80 kB
RssFile: 0 kB
RssShmem: 0 kB
VmData: 44 kB
VmStk: 132 kB
VmExe: 8 kB
VmLib: 1872 kB
VmPTE: 52 kB
VmSwap: 0 kB
HugetlbPages: 0 kB
CoreDumping: 0
Threads: 1
SigQ: 0/47895
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 1
nonvoluntary_ctxt_switches: 0
postloop
elap=4 errkill=0 errst=0
CMD: ls -l /proc/94913
ls: cannot read symbolic link '/proc/94913/cwd': No such file or directory
ls: cannot read symbolic link '/proc/94913/root': No such file or directory
ls: cannot read symbolic link '/proc/94913/exe': No such file or directory
total 0
dr-xr-xr-x. 2 xxx xxx 0 Oct 21 15:50 attr
-rw-r--r--. 1 root root 0 Oct 21 15:50 autogroup
-r--------. 1 root root 0 Oct 21 15:50 auxv
-r--r--r--. 1 root root 0 Oct 21 15:50 cgroup
--w-------. 1 root root 0 Oct 21 15:50 clear_refs
-r--r--r--. 1 root root 0 Oct 21 15:50 cmdline
-rw-r--r--. 1 root root 0 Oct 21 15:50 comm
-rw-r--r--. 1 root root 0 Oct 21 15:50 coredump_filter
-r--r--r--. 1 root root 0 Oct 21 15:50 cpuset
lrwxrwxrwx. 1 root root 0 Oct 21 15:50 cwd
-r--------. 1 root root 0 Oct 21 15:50 environ
lrwxrwxrwx. 1 root root 0 Oct 21 15:50 exe
dr-x------. 2 root root 0 Oct 21 15:50 fd
dr-x------. 2 root root 0 Oct 21 15:50 fdinfo
-rw-r--r--. 1 root root 0 Oct 21 15:50 gid_map
-r--------. 1 root root 0 Oct 21 15:50 io
-r--r--r--. 1 root root 0 Oct 21 15:50 latency
-r--r--r--. 1 root root 0 Oct 21 15:50 limits
-rw-r--r--. 1 root root 0 Oct 21 15:50 loginuid
dr-x------. 2 root root 0 Oct 21 15:50 map_files
-r--r--r--. 1 root root 0 Oct 21 15:50 maps
-rw-------. 1 root root 0 Oct 21 15:50 mem
-r--r--r--. 1 root root 0 Oct 21 15:50 mountinfo
-r--r--r--. 1 root root 0 Oct 21 15:50 mounts
-r--------. 1 root root 0 Oct 21 15:50 mountstats
dr-xr-xr-x. 2 xxx xxx 0 Oct 21 15:50 net
dr-x--x--x. 2 root root 0 Oct 21 15:50 ns
-r--r--r--. 1 root root 0 Oct 21 15:50 numa_maps
-rw-r--r--. 1 root root 0 Oct 21 15:50 oom_adj
-r--r--r--. 1 root root 0 Oct 21 15:50 oom_score
-rw-r--r--. 1 root root 0 Oct 21 15:50 oom_score_adj
-r--------. 1 root root 0 Oct 21 15:50 pagemap
-r--------. 1 root root 0 Oct 21 15:50 personality
-rw-r--r--. 1 root root 0 Oct 21 15:50 projid_map
lrwxrwxrwx. 1 root root 0 Oct 21 15:50 root
-rw-r--r--. 1 root root 0 Oct 21 15:50 sched
-r--r--r--. 1 root root 0 Oct 21 15:50 schedstat
-r--r--r--. 1 root root 0 Oct 21 15:50 sessionid
-rw-r--r--. 1 root root 0 Oct 21 15:50 setgroups
-r--r--r--. 1 root root 0 Oct 21 15:50 smaps
-r--r--r--. 1 root root 0 Oct 21 15:50 smaps_rollup
-r--------. 1 root root 0 Oct 21 15:50 stack
-r--r--r--. 1 root root 0 Oct 21 15:50 stat
-r--r--r--. 1 root root 0 Oct 21 15:50 statm
-r--r--r--. 1 root root 0 Oct 21 15:50 status
-r--------. 1 root root 0 Oct 21 15:50 syscall
dr-xr-xr-x. 3 xxx xxx 0 Oct 21 15:50 task
-r--r--r--. 1 root root 0 Oct 21 15:50 timers
-rw-rw-rw-. 1 root root 0 Oct 21 15:50 timerslack_ns
-rw-r--r--. 1 root root 0 Oct 21 15:50 uid_map
-r--r--r--. 1 root root 0 Oct 21 15:50 wchan
CMD: ls -l /proc/94913/fd
ls: cannot open directory '/proc/94913/fd': Permission denied
CMD: cat /proc/94913/status
Name: pgm2
State: Z (zombie)
Tgid: 94913
Ngid: 0
Pid: 94913
PPid: 94912
TracerPid: 0
Uid: 500 500 500 500
Gid: 500 500 500 500
FDSize: 0
Groups: 500
NStgid: 94913
NSpid: 94913
NSpgid: 94912
NSsid: 3771
Threads: 1
SigQ: 0/47895
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 2
nonvoluntary_ctxt_switches: 0
fgets
Name: pgm2
State: Z (zombie)
Tgid: 94913
Ngid: 0
Pid: 94913
PPid: 94912
TracerPid: 0
Uid: 500 500 500 500
Gid: 500 500 500 500
FDSize: 0
Groups: 500
NStgid: 94913
NSpid: 94913
NSpgid: 94912
NSsid: 3771
Threads: 1
SigQ: 0/47895
SigPnd: 0000000000000000
ShdPnd: 0000000000000000
SigBlk: 0000000000000000
SigIgn: 0000000000000000
SigCgt: 0000000000000000
CapInh: 0000000000000000
CapPrm: 0000000000000000
CapEff: 0000000000000000
CapBnd: 0000003fffffffff
CapAmb: 0000000000000000
NoNewPrivs: 0
Seccomp: 0
Speculation_Store_Bypass: thread vulnerable
Cpus_allowed: ff
Cpus_allowed_list: 0-7
Mems_allowed: 00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 2
nonvoluntary_ctxt_switches: 0
postwait
elap=4 errkill=-1 errst=-1
CMD: ls -l /proc/94913
ls: cannot access '/proc/94913': No such file or directory
CMD: ls -l /proc/94913/fd
ls: cannot access '/proc/94913/fd': No such file or directory
CMD: cat /proc/94913/status
cat: /proc/94913/status: No such file or directory
fgets
谢谢。我对时间问题感到好奇。如果等待家庭调用释放了/ proc中PID的信息,那么启动PID的进程在知道终止子进程之后如何读取状态伪文件。
Thanks. I'm (mildly) curious about the timing issues. If the wait-family call releases the information in /proc for the PID, then how does the process that launched the PID get to read the status pseudo-file after it knows the child terminated.
如果没有使用 wait
,则父级不能,因为检查活动进程的另一种方法(例如 kill(pid,0)
)仍然返回0。
Without using wait
, the parent can't know definitively/easily/cleanly because the alternate way to check for a live process (e.g. kill(pid,0)
) still returns 0. This was [somewhat] surprising to me.
根据测试程序的输出,可能的一种工作方式是进行
并检查错误(即错误表示进程已退出并处于僵尸状态)。 / proc / pid / cwd
上的readlink
Based on the test program output, one way that might work is to do a readlink
on /proc/pid/cwd
and check for error (i.e. error means process exited and is in zombie state).
另一种方法是读取 / proc / pid / status
并查找:状态:Z(僵尸)
Another way is to read /proc/pid/status
and look for: State: Z (zombie)
是否需要在等待之前打开状态文件,然后在等待返回时读取它?
Does it need to open the status file before the wait, and then read it once the wait returns?
A完成等待
之后,甚至在 / proc / pid / status $ c $上打开 pre 的流c>返回EOF。因此,没有喜悦。
After the wait
is done, even a pre-opened stream on /proc/pid/status
returns EOF. So, no joy.
还是比这还不那么狡猾? / proc文件系统上应该有一些文档(例如,man7.org上的proc(5))应涵盖这些详细信息。
Or is it less devious than that? There should be some documentation on the /proc file system — proc(5) at man7.org for example — which should cover these details.
手册页中还有其他一些文件,这些文件在进程变为僵尸时会更改(例如 / proc / pid / cmdline
)
The man page does some other files that change when the process becomes zombie (e.g. /proc/pid/cmdline
)