我如何从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)