views:

154

answers:

2

I've managed to implement the code on this listing to get a list of all the processes running and their IDs. What I need now is to extract how much time each process uses the CPU.

I've tried referring to the keys in the code, but when I try to print 'Ticks of CPU Time' I get a zero value for all of the processes. Plus, even if I did get a value I'm not sure if 'Ticks of CPU Time' is exactly what I'm looking for.

struct  vmspace *p_vmspace; /* Address space. */
struct  sigacts *p_sigacts; /* Signal actions, state (PROC ONLY). */
int p_flag;         /* P_* flags. */
char    p_stat;         /* S* process status. */
pid_t   p_pid;          /* Process identifier. */
pid_t   p_oppid;     /* Save parent pid during ptrace. XXX */
int p_dupfd;     /* Sideways return value from fdopen. XXX */
/* Mach related  */
caddr_t user_stack; /* where user stack was allocated */
void    *exit_thread;   /* XXX Which thread is exiting? */
int     p_debugger;     /* allow to debug */
boolean_t   sigwait;    /* indication to suspend */
/* scheduling */
u_int   p_estcpu;    /* Time averaged value of p_cpticks. */
int p_cpticks;   /* Ticks of cpu time. */
fixpt_t p_pctcpu;    /* %cpu for this process during p_swtime */
void    *p_wchan;    /* Sleep address. */
char    *p_wmesg;    /* Reason for sleep. */
u_int   p_swtime;    /* Time swapped in or out. */
u_int   p_slptime;   /* Time since last blocked. */
struct  itimerval p_realtimer;  /* Alarm timer. */
struct  timeval p_rtime;    /* Real time. */
u_quad_t p_uticks;      /* Statclock hits in user mode. */
u_quad_t p_sticks;      /* Statclock hits in system mode. */
u_quad_t p_iticks;      /* Statclock hits processing intr. */
int p_traceflag;        /* Kernel trace points. */
struct  vnode *p_tracep;    /* Trace to vnode. */
int p_siglist;      /* DEPRECATED */
struct  vnode *p_textvp;    /* Vnode of executable. */
int p_holdcnt;      /* If non-zero, don't swap. */
sigset_t p_sigmask; /* DEPRECATED. */
sigset_t p_sigignore;   /* Signals being ignored. */
sigset_t p_sigcatch;    /* Signals being caught by user. */
u_char  p_priority; /* Process priority. */
u_char  p_usrpri;   /* User-priority based on p_cpu and p_nice. */
char    p_nice;     /* Process "nice" value. */
char    p_comm[MAXCOMLEN+1];
struct  pgrp *p_pgrp;   /* Pointer to process group. */
struct  user *p_addr;   /* Kernel virtual addr of u-area (PROC ONLY). */
u_short p_xstat;    /* Exit status for wait; also stop signal. */
u_short p_acflag;   /* Accounting flags. */
struct  rusage *p_ru;   /* Exit information. XXX */

In fact I've also tried to print Time averaged value of p_cpticks and a few others and never got interesting values. Here is my code which is printing the information retrieved (I got it from cocoabuilder.com) :

- (NSDictionary *) getProcessList {
    NSMutableDictionary *ProcList = [[NSMutableDictionary alloc] init];

    kinfo_proc *mylist;
    size_t mycount = 0;
    mylist = (kinfo_proc *)malloc(sizeof(kinfo_proc));
    GetBSDProcessList(&mylist, &mycount);
    printf("There are %d processes.\n", (int)mycount);

NSLog(@" = = = = = = = = = = =  = = = =");
    int k;
    for(k = 0; k < mycount; k++) {
        kinfo_proc *proc = NULL;
        proc = &mylist[k];
        // NSString *processName = [NSString stringWithFormat: @"%s",proc->kp_proc.p_comm];
         //[ ProcList setObject: processName forKey: processName ];
        //  [ ProcList setObject: proc->kp_proc.p_pid forKey: processName];
          // printf("ID: %d - NAME: %s\n", proc->kp_proc.p_pid, proc->kp_proc.p_comm);
           printf("ID: %d - NAME: %s  CPU TIME: %d     \n", proc->kp_proc.p_pid, proc->kp_proc.p_comm, proc->kp_proc.p_pid );
        // Right click on p_comm and select 'jump to definition' to find other values. 
    }


    free(mylist);

    return [ProcList autorelease];
}

Thanks!

EDIT: I've just offered a bounty for this question. What I'm looking for specifically is to get the amount of time each process spends in CPU.

If, in addition to this, you can give %CPU being used by a process, that would be fantastic.

The code should be optimal in that it will be called every second and the method will be called on all running processes. Objective-C preferable.

Thanks again!

EDIT 2

Also, any comments as to why people are ignoring this question would also be helpful :)

+2  A: 

Have a look at the Darwin source for libtop.c and particularly the libtop_pinfo_update_cpu_usage() function. Note that:

  1. You'll need a basic understanding of Mach programming fundamentals to make sense of this code, as it uses task ports, etc.
  2. If you want to simply use libtop, you'll have to download the source and compile it yourself.
  3. Your process will need privileges to get at the task ports for other processes.

If all this sounds rather daunting, well… There is a way that uses less esoteric APIs: Just spawn a top process and parse its standard output. A quick glimpse over the top(1) man page turned up this little gem:

$ top -s 1 -l 3600 -stats pid,cpu,time

That is, sample once per second for 3600 seconds (one hour), and output to stdout in log form only the statistics for pid, cpu usage, and time.

Spawning and managing the child top process and then parsing its output are all straightforward Unix programming exercises.

Kaelin Colclasure
Is there any way to get a bit of sample code to see how to implement this? I'm not even really clear as to what arguments to pass through the method :(
Eric Brotto
I've edited my answer to offer a somewhat less esoteric alternative. :-) There's lots of tutorial material on using NSTask to manage a child process… I'd recommend that, and NSScanner to parse top's output.
Kaelin Colclasure
@Kaelin. Thanks so much! We are definitely getting closer to something I can manage to do. Well done! :)
Eric Brotto
+1  A: 

Have you taken a look at the struct rusage? You have listed it and commented as "Exit information" but I know that it contains the resources actually used by a process. Take a look at this page. I remember I used getrusage() for calculating the exact amount of CPU time used in my scientific calculation for my current process, so you just have to know how to query that struct for each process in you list i guess

rano
getrusage() only works for the calling process and its children.
Kaelin Colclasure
I know, I stated it above, but I believe there is a way to query other processes in a similar way
rano
@rano. This seems viable and I'm playing with it right now. Some sample code would be fantastic though ;)
Eric Brotto
@rano It seems to me that while your suggestion is quite good, it only deals with the current process. Is there anyway to apply this to all the processes?
Eric Brotto
@Eric Brotto, I'm sorry, as stated before, `getrusage()` can really be used only for the current process or its children. I can provide you some come for this functionality as I used it. My idea is that there shall be something similar to query other processes, but I do not know exactly which is.
rano
@rano, thanks for trying, but I really do need something for all the processes. :)
Eric Brotto