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:
122
src/main.c
122
src/main.c
@@ -12,21 +12,137 @@
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <glib/gi18n.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "process-window.h"
|
||||
#include "process-tree-view.h"
|
||||
#include "task-manager.h"
|
||||
|
||||
static GtkWidget *window;
|
||||
static XtmTaskManager *task_manager;
|
||||
static gboolean timeout = 0;
|
||||
|
||||
static void
|
||||
update_tree_iter (GtkTreeModel *model, GtkTreeIter *iter, Task *task)
|
||||
{
|
||||
gchar vsz[64], rss[64], cpu[16];
|
||||
|
||||
// TODO add precision for values < 1 MB
|
||||
g_snprintf (vsz, 64, _("%lu MB"), task->vsz / 1024 / 1024);
|
||||
g_snprintf (rss, 64, _("%lu MB"), task->rss / 1024 / 1024);
|
||||
// TODO make precision optional
|
||||
g_snprintf (cpu, 16, _("%.2f%%"), task->cpu_user + task->cpu_system);
|
||||
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), iter,
|
||||
XTM_PTV_COLUMN_PPID, task->ppid,
|
||||
XTM_PTV_COLUMN_STATE, task->state,
|
||||
XTM_PTV_COLUMN_VSZ, task->vsz,
|
||||
XTM_PTV_COLUMN_VSZ_STR, vsz,
|
||||
XTM_PTV_COLUMN_RSS, task->rss,
|
||||
XTM_PTV_COLUMN_RSS_STR, rss,
|
||||
XTM_PTV_COLUMN_CPU, task->cpu_user + task->cpu_system,
|
||||
XTM_PTV_COLUMN_CPU_STR, cpu,
|
||||
XTM_PTV_COLUMN_PRIORITY, task->prio,
|
||||
-1);
|
||||
}
|
||||
|
||||
static void
|
||||
add_tree_iter (GtkTreeModel *model, Task *task)
|
||||
{
|
||||
GtkTreeIter iter;
|
||||
gtk_list_store_append (GTK_LIST_STORE (model), &iter);
|
||||
gtk_list_store_set (GTK_LIST_STORE (model), &iter,
|
||||
XTM_PTV_COLUMN_COMMAND, task->cmdline,
|
||||
XTM_PTV_COLUMN_PID, task->pid,
|
||||
XTM_PTV_COLUMN_STATE, task->state,
|
||||
XTM_PTV_COLUMN_UID, task->uid_name,
|
||||
-1);
|
||||
update_tree_iter (model, &iter, task);
|
||||
}
|
||||
|
||||
static void
|
||||
update_tree_model (const GArray *task_list)
|
||||
{
|
||||
GtkTreeModel *model;
|
||||
GtkTreeIter iter;
|
||||
Task *task;
|
||||
guint i;
|
||||
gboolean valid;
|
||||
|
||||
model = xtm_process_window_get_model (XTM_PROCESS_WINDOW (window));
|
||||
|
||||
// TODO pick a timestamp for started/terminated tasks to keep them momentary (red/green color, italic, ...)
|
||||
/* Remove terminated tasks */
|
||||
valid = gtk_tree_model_get_iter_first (model, &iter);
|
||||
while (valid)
|
||||
{
|
||||
guint pid;
|
||||
gboolean found = FALSE;
|
||||
|
||||
gtk_tree_model_get (model, &iter, XTM_PTV_COLUMN_PID, &pid, -1);
|
||||
for (i = 0; i < task_list->len; i++)
|
||||
{
|
||||
task = &g_array_index (task_list, Task, i);
|
||||
if (pid != task->pid)
|
||||
continue;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == FALSE)
|
||||
gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
|
||||
|
||||
valid = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
|
||||
/* Append started tasks and update existing ones */
|
||||
for (i = 0; i < task_list->len; i++)
|
||||
{
|
||||
guint pid;
|
||||
gboolean found = FALSE;
|
||||
|
||||
task = &g_array_index (task_list, Task, i);
|
||||
valid = gtk_tree_model_get_iter_first (model, &iter);
|
||||
while (valid)
|
||||
{
|
||||
gtk_tree_model_get (model, &iter, XTM_PTV_COLUMN_PID, &pid, -1);
|
||||
|
||||
if (pid == task->pid)
|
||||
{
|
||||
// TODO check if elements have to be updated, updating everything always is a CPU hog
|
||||
update_tree_iter (model, &iter, task);
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
valid = gtk_tree_model_iter_next (model, &iter);
|
||||
}
|
||||
|
||||
if (found == FALSE)
|
||||
{
|
||||
add_tree_iter (model, task);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
timeout_cb ()
|
||||
init_timeout ()
|
||||
{
|
||||
guint num_processes;
|
||||
gfloat cpu, memory, swap;
|
||||
const GArray *task_list;
|
||||
|
||||
xtm_task_manager_get_system_info (task_manager, &num_processes, &cpu, &memory, &swap);
|
||||
xtm_process_window_set_system_info (XTM_PROCESS_WINDOW (window), num_processes, cpu, memory, swap);
|
||||
|
||||
task_list = xtm_task_manager_get_task_list (task_manager);
|
||||
update_tree_model (task_list);
|
||||
|
||||
if (timeout == 0)
|
||||
timeout = g_timeout_add (1000, init_timeout, NULL);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
@@ -45,12 +161,14 @@ int main (int argc, char *argv[])
|
||||
task_manager = xtm_task_manager_new ();
|
||||
g_message ("Running as %s on %s", xtm_task_manager_get_username (task_manager), xtm_task_manager_get_hostname (task_manager));
|
||||
|
||||
g_timeout_add (1000, timeout_cb, NULL);
|
||||
init_timeout ();
|
||||
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (gtk_main_quit), NULL);
|
||||
|
||||
gtk_main ();
|
||||
|
||||
if (timeout > 0)
|
||||
g_source_remove (timeout);
|
||||
g_object_unref (window);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -34,20 +34,6 @@ struct _XtmProcessTreeView
|
||||
};
|
||||
G_DEFINE_TYPE (XtmProcessTreeView, xtm_process_tree_view, GTK_TYPE_TREE_VIEW)
|
||||
|
||||
enum
|
||||
{
|
||||
COLUMN_COMMAND,
|
||||
COLUMN_PID,
|
||||
COLUMN_PPID,
|
||||
COLUMN_STATE,
|
||||
COLUMN_VSZ,
|
||||
COLUMN_RSS,
|
||||
COLUMN_UID,
|
||||
COLUMN_CPU,
|
||||
COLUMN_PRIORITY,
|
||||
N_COLUMNS,
|
||||
};
|
||||
|
||||
static gboolean treeview_clicked (XtmProcessTreeView *treeview, GdkEventButton *event);
|
||||
static void settings_changed (GObject *object, GParamSpec *pspec, XtmProcessTreeView *treeview);
|
||||
static int sort_by_string (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data);
|
||||
@@ -74,10 +60,10 @@ xtm_process_tree_view_init (XtmProcessTreeView *treeview)
|
||||
g_object_get (treeview->settings, "sort-column-id", &sort_column_id, "sort-type", &sort_type, NULL);
|
||||
g_signal_connect (treeview->settings, "notify", G_CALLBACK (settings_changed), treeview);
|
||||
|
||||
treeview->model = gtk_list_store_new (9, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
|
||||
G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
|
||||
treeview->model = gtk_list_store_new (XTM_PTV_N_COLUMNS, G_TYPE_STRING, G_TYPE_UINT, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_UINT64,
|
||||
G_TYPE_STRING, G_TYPE_UINT64, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_FLOAT, G_TYPE_STRING, G_TYPE_INT);
|
||||
|
||||
g_object_set (treeview, "search-column", COLUMN_COMMAND, "model", treeview->model, NULL);
|
||||
g_object_set (treeview, "search-column", XTM_PTV_COLUMN_COMMAND, "model", treeview->model, NULL);
|
||||
|
||||
cell_text = gtk_cell_renderer_text_new();
|
||||
|
||||
@@ -87,61 +73,60 @@ xtm_process_tree_view_init (XtmProcessTreeView *treeview)
|
||||
cell_cmdline = gtk_cell_renderer_text_new ();
|
||||
g_object_set (cell_cmdline, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
|
||||
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Task"), cell_cmdline, "text", COLUMN_COMMAND, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Task"), cell_cmdline, "text", XTM_PTV_COLUMN_COMMAND, NULL);
|
||||
g_object_set (column, "expand", TRUE, "reorderable", FALSE, "resizable", TRUE, "visible", TRUE, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_COMMAND);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_COMMAND);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-pid", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("PID"), cell_right_aligned, "text", COLUMN_PID, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("PID"), cell_right_aligned, "text", XTM_PTV_COLUMN_PID, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_PID);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_PID);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-ppid", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("PPID"), cell_right_aligned, "text", COLUMN_PPID, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("PPID"), cell_right_aligned, "text", XTM_PTV_COLUMN_PPID, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_PPID);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_PPID);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-state", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("State"), cell_text, "text", COLUMN_STATE, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("State"), cell_text, "text", XTM_PTV_COLUMN_STATE, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_STATE);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_STATE);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-vsz", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("VSZ"), cell_right_aligned, "text", COLUMN_VSZ, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("VSZ"), cell_right_aligned, "text", XTM_PTV_COLUMN_VSZ_STR, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_VSZ);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_VSZ);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-rss", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("RSS"), cell_right_aligned, "text", COLUMN_RSS, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("RSS"), cell_right_aligned, "text", XTM_PTV_COLUMN_RSS_STR, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_RSS);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_RSS);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-uid", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("UID"), cell_text, "text", COLUMN_UID, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("UID"), cell_text, "text", XTM_PTV_COLUMN_UID, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_UID);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_UID);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-cpu", &visible, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("CPU"), cell_right_aligned, "text", COLUMN_CPU, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("CPU"), cell_right_aligned, "text", XTM_PTV_COLUMN_CPU_STR, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_CPU);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_CPU);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
g_object_get (treeview->settings, "column-priority", &visible, NULL);
|
||||
/* TRANSLATORS: “Prio.” is short for Priority, it appears in the tree view header. */
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Prio."), cell_right_aligned, "text", COLUMN_PRIORITY, NULL);
|
||||
column = gtk_tree_view_column_new_with_attributes (_("Prio."), cell_right_aligned, "text", XTM_PTV_COLUMN_PRIORITY, NULL);
|
||||
g_object_set (column, "expand", FALSE, "reorderable", FALSE, "resizable", TRUE, "visible", visible, NULL);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), COLUMN_PRIORITY);
|
||||
gtk_tree_view_column_set_sort_column_id (GTK_TREE_VIEW_COLUMN (column), XTM_PTV_COLUMN_PRIORITY);
|
||||
gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
|
||||
|
||||
gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (treeview->model), sort_by_string, NULL, NULL);
|
||||
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (treeview->model), sort_column_id, sort_type);
|
||||
|
||||
g_signal_connect (treeview, "button-press-event", G_CALLBACK (treeview_clicked), NULL);
|
||||
@@ -165,27 +150,27 @@ treeview_clicked (XtmProcessTreeView *treeview, GdkEventButton *event)
|
||||
static void
|
||||
settings_changed (GObject *object, GParamSpec *pspec, XtmProcessTreeView *treeview)
|
||||
{
|
||||
if (g_strstr_len (pspec->name, -1, "column-") != NULL)
|
||||
if (g_str_has_prefix (pspec->name, "column-"))
|
||||
{
|
||||
gboolean visible;
|
||||
gushort column_id;
|
||||
|
||||
if (!g_strcmp0 (pspec->name, "column-uid"))
|
||||
column_id = COLUMN_UID;
|
||||
column_id = XTM_PTV_COLUMN_UID;
|
||||
else if (!g_strcmp0 (pspec->name, "column-pid"))
|
||||
column_id = COLUMN_PID;
|
||||
column_id = XTM_PTV_COLUMN_PID;
|
||||
else if (!g_strcmp0 (pspec->name, "column-ppid"))
|
||||
column_id = COLUMN_PPID;
|
||||
column_id = XTM_PTV_COLUMN_PPID;
|
||||
else if (!g_strcmp0 (pspec->name, "column-state"))
|
||||
column_id = COLUMN_STATE;
|
||||
column_id = XTM_PTV_COLUMN_STATE;
|
||||
else if (!g_strcmp0 (pspec->name, "column-vsz"))
|
||||
column_id = COLUMN_VSZ;
|
||||
column_id = XTM_PTV_COLUMN_VSZ_STR;
|
||||
else if (!g_strcmp0 (pspec->name, "column-rss"))
|
||||
column_id = COLUMN_RSS;
|
||||
column_id = XTM_PTV_COLUMN_RSS_STR;
|
||||
else if (!g_strcmp0 (pspec->name, "column-cpu"))
|
||||
column_id = COLUMN_CPU;
|
||||
column_id = XTM_PTV_COLUMN_CPU_STR;
|
||||
else if (!g_strcmp0 (pspec->name, "column-priority"))
|
||||
column_id = COLUMN_PRIORITY;
|
||||
column_id = XTM_PTV_COLUMN_PRIORITY;
|
||||
|
||||
g_object_get (object, pspec->name, &visible, NULL);
|
||||
gtk_tree_view_column_set_visible (gtk_tree_view_get_column (GTK_TREE_VIEW (treeview), column_id), visible);
|
||||
@@ -198,46 +183,6 @@ settings_changed (GObject *object, GParamSpec *pspec, XtmProcessTreeView *treevi
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sort_by_string (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, gpointer user_data)
|
||||
{
|
||||
gint sort_column_id;
|
||||
GtkSortType order;
|
||||
gchar *str1 = NULL, *str2 = NULL;
|
||||
gchar *cstr1 = NULL, *cstr2 = NULL;
|
||||
gint ret = 0;
|
||||
|
||||
g_debug (__func__);
|
||||
|
||||
if (!gtk_tree_sortable_get_sort_column_id (GTK_TREE_SORTABLE (model), &sort_column_id, &order))
|
||||
{
|
||||
g_debug ("sort column default or unsorted: %d", sort_column_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
gtk_tree_model_get(model, a, sort_column_id, &str1, -1);
|
||||
gtk_tree_model_get(model, b, sort_column_id, &str2, -1);
|
||||
|
||||
cstr1 = g_utf8_collate_key_for_filename (str1, -1);
|
||||
cstr2 = g_utf8_collate_key_for_filename (str2, -1);
|
||||
|
||||
if (cstr1 != NULL && cstr2 != NULL)
|
||||
{
|
||||
ret = g_utf8_collate (cstr1, cstr2);
|
||||
}
|
||||
else if ((cstr1 == NULL && cstr2 != NULL) || (cstr1 != NULL && cstr2 == NULL))
|
||||
{
|
||||
ret = (cstr1 == NULL) ? -1 : 1;
|
||||
}
|
||||
|
||||
g_free (str1);
|
||||
g_free (str2);
|
||||
g_free (cstr1);
|
||||
g_free (cstr2);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
GtkWidget *
|
||||
|
||||
@@ -16,6 +16,23 @@
|
||||
|
||||
#include <glib-object.h>
|
||||
|
||||
enum
|
||||
{
|
||||
XTM_PTV_COLUMN_COMMAND,
|
||||
XTM_PTV_COLUMN_PID,
|
||||
XTM_PTV_COLUMN_PPID,
|
||||
XTM_PTV_COLUMN_STATE,
|
||||
XTM_PTV_COLUMN_VSZ,
|
||||
XTM_PTV_COLUMN_VSZ_STR,
|
||||
XTM_PTV_COLUMN_RSS,
|
||||
XTM_PTV_COLUMN_RSS_STR,
|
||||
XTM_PTV_COLUMN_UID,
|
||||
XTM_PTV_COLUMN_CPU,
|
||||
XTM_PTV_COLUMN_CPU_STR,
|
||||
XTM_PTV_COLUMN_PRIORITY,
|
||||
XTM_PTV_N_COLUMNS,
|
||||
};
|
||||
|
||||
#define XTM_TYPE_PROCESS_TREE_VIEW (xtm_process_tree_view_get_type ())
|
||||
#define XTM_PROCESS_TREE_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), XTM_TYPE_PROCESS_TREE_VIEW, XtmProcessTreeView))
|
||||
#define XTM_PROCESS_TREE_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), XTM_TYPE_PROCESS_TREE_VIEW, XtmProcessTreeViewClass))
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ xtm_task_manager_class_init (XtmTaskManagerClass *klass)
|
||||
static void
|
||||
xtm_task_manager_init (XtmTaskManager *manager)
|
||||
{
|
||||
manager->tasks = g_array_new (FALSE, FALSE, sizeof (Task));
|
||||
get_owner_uid (&(manager->owner_uid), &(manager->owner_uid_name));
|
||||
manager->hostname = get_hostname ();
|
||||
}
|
||||
@@ -74,6 +75,7 @@ static void
|
||||
xtm_task_manager_finalize (GObject *object)
|
||||
{
|
||||
XtmTaskManager *manager = XTM_TASK_MANAGER (object);
|
||||
g_array_free (manager->tasks, TRUE);
|
||||
g_free (manager->owner_uid_name);
|
||||
g_free (manager->hostname);
|
||||
}
|
||||
@@ -128,18 +130,13 @@ xtm_task_manager_get_hostname (XtmTaskManager *manager)
|
||||
return manager->hostname;
|
||||
}
|
||||
|
||||
GArray *
|
||||
xtm_task_manager_get_tasklist (XtmTaskManager *manager)
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
xtm_task_manager_get_system_info (XtmTaskManager *manager, guint *num_processes, gfloat *cpu, gfloat *memory, gfloat *swap)
|
||||
{
|
||||
guint64 memory_used, swap_used;
|
||||
|
||||
/* Set number of processes */
|
||||
*num_processes = 0;//manager->tasks->len;
|
||||
*num_processes = manager->tasks->len;
|
||||
|
||||
/* Set memory and swap usage */
|
||||
get_memory_usage (&manager->memory_total, &manager->memory_free, &manager->memory_cache, &manager->memory_buffers,
|
||||
@@ -156,6 +153,87 @@ xtm_task_manager_get_system_info (XtmTaskManager *manager, guint *num_processes,
|
||||
*cpu = manager->cpu_user + manager->cpu_system;
|
||||
}
|
||||
|
||||
const GArray *
|
||||
xtm_task_manager_get_task_list (XtmTaskManager *manager)
|
||||
{
|
||||
GArray *array;
|
||||
guint i;
|
||||
|
||||
if (manager->tasks->len == 0)
|
||||
{
|
||||
get_task_list (manager->tasks);
|
||||
#if 1|DEBUG
|
||||
{
|
||||
gint i;
|
||||
for (i = 0; i < manager->tasks->len; i++)
|
||||
{
|
||||
Task *task = &g_array_index (manager->tasks, Task, i);
|
||||
g_print ("%5d %5s %15s %.50s\n", task->pid, task->uid_name, task->name, task->cmdline);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return manager->tasks;
|
||||
}
|
||||
|
||||
/* Retrieve new task list */
|
||||
array = g_array_new (FALSE, FALSE, sizeof (Task));
|
||||
get_task_list (array);
|
||||
|
||||
/* Remove terminated tasks */
|
||||
for (i = 0; i < manager->tasks->len; i++)
|
||||
{
|
||||
guint j;
|
||||
Task *task = &g_array_index (manager->tasks, Task, i);
|
||||
gboolean found = FALSE;
|
||||
|
||||
for (j = 0; j < array->len; j++)
|
||||
{
|
||||
Task *tasktmp = &g_array_index (array, Task, j);
|
||||
if (task->pid != tasktmp->pid)
|
||||
continue;
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == FALSE)
|
||||
g_array_remove_index (manager->tasks, i);
|
||||
}
|
||||
|
||||
/* Append started tasks and update existing ones */
|
||||
for (i = 0; i < array->len; i++)
|
||||
{
|
||||
guint j;
|
||||
Task *tasktmp = &g_array_index (array, Task, i);
|
||||
gboolean found = FALSE;
|
||||
|
||||
for (j = 0; j < manager->tasks->len; j++)
|
||||
{
|
||||
Task *task = &g_array_index (manager->tasks, Task, j);
|
||||
if (task->pid != tasktmp->pid)
|
||||
continue;
|
||||
|
||||
found = TRUE;
|
||||
|
||||
task->ppid = tasktmp->ppid;
|
||||
if (g_strcmp0 (task->state, tasktmp->state))
|
||||
g_strlcpy (task->state, tasktmp->state, sizeof (task->state));
|
||||
task->cpu_user = tasktmp->cpu_user;
|
||||
task->cpu_system = tasktmp->cpu_system;
|
||||
task->rss = tasktmp->rss;
|
||||
task->vsz = tasktmp->vsz;
|
||||
task->prio = tasktmp->prio;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found == FALSE)
|
||||
g_array_append_val (manager->tasks, tasktmp);
|
||||
}
|
||||
|
||||
g_array_free (array, TRUE);
|
||||
|
||||
return manager->tasks;
|
||||
}
|
||||
|
||||
void
|
||||
xtm_task_manager_send_signal_to_pid (XtmTaskManager *manager)
|
||||
{
|
||||
|
||||
@@ -23,17 +23,18 @@
|
||||
typedef struct _Task Task;
|
||||
struct _Task
|
||||
{
|
||||
guint uid;
|
||||
gchar uid_name[64];
|
||||
guint pid;
|
||||
guint ppid;
|
||||
gchar program_name[64];
|
||||
gchar full_cmdline[255];
|
||||
gchar state[16];
|
||||
gfloat cpu;
|
||||
guint64 memory_vsz;
|
||||
guint64 memory_rss;
|
||||
gushort priority;
|
||||
guint uid;
|
||||
gchar uid_name[256];
|
||||
guint pid;
|
||||
guint ppid;
|
||||
gchar name[256];
|
||||
gchar cmdline[1024];
|
||||
gchar state[16];
|
||||
gfloat cpu_user;
|
||||
gfloat cpu_system;
|
||||
guint64 vsz;
|
||||
guint64 rss;
|
||||
gshort prio;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -42,7 +43,7 @@ struct _Task
|
||||
|
||||
gboolean get_memory_usage (guint64 *memory_total, guint64 *memory_free, guint64 *memory_cache, guint64 *memory_buffers, guint64 *swap_total, guint64 *swap_free);
|
||||
gboolean get_cpu_usage (gushort *cpu_count, gfloat *cpu_user, gfloat *cpu_system);
|
||||
//gboolean get_task_list (GArray *task_list);
|
||||
gboolean get_task_list (GArray *task_list);
|
||||
//void send_signal_to_task (gint task_id, gint signal);
|
||||
//void set_priority_to_task (gint task_id, gint prio);
|
||||
|
||||
@@ -64,5 +65,6 @@ XtmTaskManager * xtm_task_manager_new ();
|
||||
const gchar * xtm_task_manager_get_username (XtmTaskManager *manager);
|
||||
const gchar * xtm_task_manager_get_hostname (XtmTaskManager *manager);
|
||||
void xtm_task_manager_get_system_info (XtmTaskManager *manager, guint *num_processes, gfloat *cpu, gfloat *memory, gfloat *swap);
|
||||
const GArray * xtm_task_manager_get_task_list (XtmTaskManager *manager);
|
||||
|
||||
#endif /* !TASK_MANAGER_H */
|
||||
|
||||
Reference in New Issue
Block a user