Class: Sys::ProcTable

Inherits:
Object
  • Object
show all
Defined in:
ext/darwin/sys/proctable.c

Defined Under Namespace

Classes: Error

Constant Summary collapse

VERSION =

The version of the sys-proctable library

0.9.1

Class Method Summary collapse

Class Method Details

.fieldsObject

Returns an array of fields that each ProcTableStruct will contain. This may be useful if you want to know in advance what fields are available without having to perform at least one read of the /proc table.



208
209
210
211
212
213
214
215
216
217
# File 'ext/darwin/sys/proctable.c', line 208

static VALUE pt_fields(VALUE klass){
   VALUE v_array = rb_ary_new();
   int size = sizeof(fields) / sizeof(fields[0]);
   int i;

   for(i = 0; i < size; i++)
      rb_ary_push(v_array, rb_str_new2(fields[i]));

   return v_array;
}

.ps(pid = nil) ⇒ Object .ps(pid = nil) {|ps| ... } ⇒ Object

In block form, yields a ProcTableStruct for each process entry that you have rights to. This method returns an array of ProcTableStruct’s in non-block form.

If a pid is provided, then only a single ProcTableStruct is yielded or returned, or nil if no process information is found for that pid.

Overloads:

  • .ps(pid = nil) {|ps| ... } ⇒ Object

    Yields:



43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'ext/darwin/sys/proctable.c', line 43

static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
   int err;
   char state[8];
   struct kinfo_proc* procs;
   int count;                     /* Holds total number of processes */
   int i = 0;
   VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
   VALUE v_pstruct = Qnil;
   VALUE v_array = rb_ary_new();
   size_t length;
   char args[ARGS_MAX_LEN+1];

   // Passed into sysctl call
   static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};

   rb_scan_args(argc, argv, "01", &v_pid);

   // Get size of proc kproc buffer
   err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0);

   if(err == -1)
      rb_raise(cProcTableError, strerror(errno));

   // Populate the kproc buffer
   procs = malloc(length);

   if(procs == NULL)
      rb_raise(cProcTableError, strerror(errno));

   err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0);

   if(err == -1)
      rb_raise(cProcTableError, strerror(errno));

   // If we're here, we got our list
   count = length / sizeof(struct kinfo_proc);

   for(i = 0; i < count; i++) {
      v_tty_num = Qnil;
      v_tty_dev = Qnil;
      v_start_time = Qnil;

      // If a PID is provided, skip unless the PID matches
      if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) )
         continue;

      *args = '\0';

      /* Query the command line args */
      /* TODO: Cmd line not working for now - fix */

      /*args_mib[ARGS_MIB_LEN - 1] = procs[i].kp_proc.p_pid;
      args_err = sysctl( (int *) args_mib, ARGS_MIB_LEN, args, &args_size, NULL, 0);

      if(args_err >= 0) {
         fprintf(stderr, "Ret: %d LEN: %d\n", err, args_size);
         char *c;
         for(c = args; c < args+args_size; c++)
            if(*c == '\0') *c = ' ';
         args[args_size] = '\0';
      } else {
         fprintf(stderr, "err: %s LEN: %d\n", strerror(errno), args_size);
      }*/

      // Get the start time of the process
      v_start_time = rb_time_new(
         procs[i].kp_proc.p_un.__p_starttime.tv_sec,
         procs[i].kp_proc.p_un.__p_starttime.tv_usec
      );

      // Get the state of the process
      switch(procs[i].kp_proc.p_stat)
      {
         case SIDL:
            strcpy(state, "idle");
            break;
         case SRUN:
            strcpy(state, "run");
            break;
         case SSLEEP:
            strcpy(state, "sleep");
            break;
         case SSTOP:
            strcpy(state, "stop");
            break;
         case SZOMB:
            strcpy(state, "zombie");
            break;
         default:
            strcpy(state, "unknown");
            break;
      }

      // Get ttynum and ttydev. If ttynum is -1, there is no tty.
      if(procs[i].kp_eproc.e_tdev != -1){
         v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
         v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
      }

      v_pstruct = rb_struct_new(
         sProcStruct,
         INT2FIX(procs[i].kp_proc.p_pid),
         INT2FIX(procs[i].kp_eproc.e_ppid),
         INT2FIX(procs[i].kp_eproc.e_pgid),
         INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
         INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
         rb_str_new2(procs[i].kp_proc.p_comm),
         rb_str_new2(state),
         rb_float_new(procs[i].kp_proc.p_pctcpu),
         Qnil,
         v_tty_num,
         v_tty_dev,
         rb_str_new2(procs[i].kp_eproc.e_wmesg),
         INT2FIX(procs[i].kp_proc.p_rtime.tv_sec),
         INT2FIX(procs[i].kp_proc.p_priority),
         INT2FIX(procs[i].kp_proc.p_usrpri),
         INT2FIX(procs[i].kp_proc.p_nice),
         rb_str_new2(args),
         v_start_time,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil,
         (procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil
      );

      OBJ_FREEZE(v_pstruct); // This is read-only data

      if(rb_block_given_p())
         rb_yield(v_pstruct);
      else
         rb_ary_push(v_array, v_pstruct);
   }

   if(procs) free(procs);

   if(!rb_block_given_p()){
      if(NIL_P(v_pid))
         return v_array;
      else
         return v_pstruct;
   }

   return Qnil;
}