Show list of tasks

Provide the list of tasks through a GArray and parse it in main.c to
update the GtkTreeModel.
This commit is contained in:
Mike Massonnet
2010-05-05 08:53:49 +02:00
parent 71d1684696
commit a02bf69573
6 changed files with 443 additions and 112 deletions

View File

@@ -9,11 +9,18 @@
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <unistd.h>
#include <string.h>
#include <glib.h>
#include "task-manager.h"
static gushort _cpu_count = 0;
gboolean
get_memory_usage (guint64 *memory_total, guint64 *memory_free, guint64 *memory_cache, guint64 *memory_buffers, guint64 *swap_total, guint64 *swap_free)
{
@@ -23,9 +30,7 @@ get_memory_usage (guint64 *memory_total, guint64 *memory_free, guint64 *memory_c
gushort found = 0;
if ((file = fopen (filename, "r")) == NULL)
{
return FALSE;
}
while (found < 6 && fgets (buffer, 1024, file) != NULL)
{
@@ -58,21 +63,19 @@ get_cpu_usage (gushort *cpu_count, gfloat *cpu_user, gfloat *cpu_system)
static gulong cur_jiffies_system = 0, old_jiffies_system = 0;
static gulong cur_jiffies = 0, old_jiffies = 0;
gulong user, user_nice, system, idle;
gushort count = 0;
if ((file = fopen (filename, "r")) == NULL)
{
return FALSE;
}
fgets (buffer, 1024, file);
sscanf (buffer, "cpu\t%u %u %u %u", &user, &user_nice, &system, &idle);
_cpu_count = 0;
while (fgets (buffer, 1024, file) != NULL)
{
if (buffer[0] != 'c' && buffer[1] != 'p' && buffer[2] != 'u')
break;
count += 1;
_cpu_count += 1;
}
fclose (file);
@@ -86,7 +89,175 @@ get_cpu_usage (gushort *cpu_count, gfloat *cpu_user, gfloat *cpu_system)
*cpu_user = (old_jiffies > 0) ? (cur_jiffies_user - old_jiffies_user) * 100 / (gdouble)(cur_jiffies - old_jiffies) : 0;
*cpu_system = (old_jiffies > 0) ? (cur_jiffies_system - old_jiffies_system) * 100 / (gdouble)(cur_jiffies - old_jiffies) : 0;
*cpu_count = (count != 0) ? count : 1;
*cpu_count = (_cpu_count > 0) ? _cpu_count : 1;
_cpu_count = *cpu_count;
return TRUE;
}
static inline int get_pagesize ()
{
static int pagesize = 0;
if (pagesize == 0)
{
pagesize = sysconf (_SC_PAGESIZE);
if (pagesize == 0)
pagesize = 4096;
}
return pagesize;
}
static void
get_task_cmdline (Task *task)
{
FILE *file;
gchar filename[96];
gint i;
gchar c;
snprintf (filename, 96, "/proc/%i/cmdline", task->pid);
if ((file = fopen (filename, "r")) == NULL)
return;
/* Drop parentheses around task->name */
// FIXME comm concats the name to 15 chars
{
gchar *p;
g_strlcpy (task->name, &task->name[1], sizeof (task->name));
p = g_strrstr (task->name, ")");
*p = '\0';
}
/* Read byte per byte until EOF */
for (i = 0; (c = fgetc (file)) != EOF && i < sizeof (task->cmdline) - 1; i++)
task->cmdline[i] = (c == '\0') ? ' ' : c;
if (task->cmdline[i-1] == ' ')
task->cmdline[i-1] = '\0';
fclose (file);
/* Kernel processes don't have a cmdline nor an exec path */
if (i == 0)
{
size_t len = strlen (task->name);
g_strlcpy (&task->cmdline[1], task->name, len + 1);
task->cmdline[0] = '[';
task->cmdline[len+1] = ']';
task->cmdline[len+2] = '\0';
}
}
static gboolean
get_task_details (guint pid, Task *task)
{
FILE *file;
gchar filename[96];
gchar buffer[1024];
snprintf (filename, 96, "/proc/%d/stat", pid);
if ((file = fopen (filename, "r")) == NULL)
return FALSE;
fgets (buffer, 1024, file);
fclose (file);
{
gchar dummy[255];
gint idummy;
static gulong cur_j_user, cur_j_system;
static gulong old_j_user, old_j_system;
struct passwd *pw;
struct stat sstat;
sscanf(buffer, "%i %255s %1s %i %i %i %i %i %255s %255s %255s %255s %255s %i %i %i %i %i %i %i %i %i %i %i %255s %255s %255s %i %255s %255s %255s %255s %255s %255s %255s %255s %255s %255s %i %255s %255s",
&task->pid, // processid
task->name, // processname
task->state, // processstate
&task->ppid, // parentid
&idummy, // processs groupid
&idummy, // session id
&idummy, // tty id
&idummy, // tpgid the process group ID of the process running on tty of the process
dummy, // flags
dummy, // minflt minor faults the process has maid
dummy, // cminflt
dummy, // majflt
dummy, // cmajflt
&cur_j_user, // utime the number of jiffies that this process has scheduled in user mode
&cur_j_system, // stime " system mode
&idummy, // cutime " waited for children in user mode
&idummy, // cstime " system mode
&idummy, // priority (nice value + fifteen)
&task->prio, // nice range from 19 to -19
&idummy, // hardcoded 0
&idummy, // itrealvalue time in jiffies to next SIGALRM send to this process
&idummy, // starttime jiffies the process startet after system boot
&task->vsz, // vsize in bytes
&task->rss, // rss (number of pages in real memory)
dummy, // rlim limit in bytes for rss
dummy, // startcode
dummy, // endcode
&idummy, // startstack
dummy, // kstkesp value of esp (stack pointer)
dummy, // kstkeip value of EIP (instruction pointer)
dummy, // signal. bitmap of pending signals
dummy, // blocked: bitmap of blocked signals
dummy, // sigignore: bitmap of ignored signals
dummy, // sigcatch: bitmap of catched signals
dummy, // wchan
dummy, // nswap
dummy, // cnswap
dummy, // exit_signal
&idummy, // CPU number last executed on
dummy,
dummy
);
task->rss *= get_pagesize ();
task->cpu_user = (old_j_user > 0 && _cpu_count > 0) ? (cur_j_user - old_j_user) / (gfloat)_cpu_count : 0;
task->cpu_system = (old_j_system > 0 && _cpu_count > 0) ? (cur_j_system - old_j_system) / (gfloat)_cpu_count : 0;
stat (filename, &sstat);
pw = getpwuid (sstat.st_uid);
task->uid = sstat.st_uid;
g_strlcpy (task->uid_name, (pw != NULL) ? pw->pw_name : "nobody", sizeof (task->uid_name));
}
get_task_cmdline (task);
return TRUE;
}
gboolean
get_task_list (GArray *task_list)
{
GDir *dir;
const gchar *name;
guint pid;
Task task = { 0 };
if ((dir = g_dir_open ("/proc", 0, NULL)) == NULL)
return FALSE;
while ((name = g_dir_read_name(dir)) != NULL)
{
if ((pid = (guint)g_ascii_strtoull (name, NULL, 0)) > 0)
{
if (get_task_details (pid, &task))
{
g_array_append_val (task_list, task);
}
}
}
g_dir_close (dir);
return TRUE;
}