📄 mem.c
字号:
/* GKrellM| Copyright (C) 1999-2006 Bill Wilson|| Author: Bill Wilson billw@gkrellm.net| Latest versions might be found at: http://gkrellm.net|| This program is free software which I release under the GNU General Public| License. You may redistribute and/or modify this program under the terms| of that license as published by the Free Software Foundation; either| version 2 of the License, or (at your option) any later version.|| This program is distributed in the hope that it will be useful,| but WITHOUT ANY WARRANTY; without even the implied warranty of| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the| GNU General Public License for more details. Version 2 is in the| COPYRIGHT file in the top level directory of this distribution.| | To get a copy of the GNU General Puplic License, write to the Free Software| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA*/#include "gkrellm.h"#include "gkrellm-private.h"#include "gkrellm-sysdeps.h"#include "pixmaps/mem/krell_buffers.xpm"#include "pixmaps/mem/krell_cache.xpm" /* The mem monitor has two extra krells which can be themed. | So, the theme "mem" subdir can have: | bg_panel.png | krell.png | krell_buffers.png # an extension image, defaults to included xpm | krell_cache.png # an extension image, defaults to included xpm | | The gkrellmrc can have theme extension variables for these extra krells: | set_integer mem_krell_buffers_yoff n | set_integer mem_krell_buffers_depth n | set_integer mem_krell_buffers_x_hot n | set_integer mem_krell_cache_yoff n | set_integer mem_krell_cache_depth n | set_integer mem_krell_cache_x_hot n */#define MIN_GRID_RES 20#define MAX_GRID_RES 100000#define DEFAULT_GRID_RES 1000#define DEFAULT_SWAP_CHART_HEIGHT 20#define DEFAULT_FORMAT _("$t - $f free")#define MEG(x) ((gulong)(((x) + (1 << 19)) >> 20))typedef struct { GkrellmPanel *panel; GkrellmKrell *krell_used, /* Meter styled, shows fraction used */ *krell_delta, /* Chart styled, for page in/out deltas */ *krell_buffers, *krell_cache; gchar *label, *data_format, /* Format string for scrolling text */ *data_format_shadow; /* shadow format for gdk_draw compat */ gint style_id; gint x_label; GkrellmDecal *decal_label; gboolean label_is_data, restore_label, /* Helper to know when to toggle data fmt off*/ mouse_entered, all_krells; gint enabled; GkrellmLauncher launch; GkrellmAlert *alert; guint64 total, /* Total memory or swap in system */ used, /* Amount of memory (calulated) or swap used */ free, /* Not used by swap monitor */ shared, /* Not used by swap monitor */ buffers, /* Not used by swap monitor */ cached; /* Not used by swap monitor */ } MeminfoMeter;typedef struct { GtkWidget *vbox; GkrellmChart *chart; GkrellmChartdata *in_cd, *out_cd; GkrellmChartconfig *chart_config; gboolean enabled; gboolean extra_info; gulong page_in, page_out; } MeminfoChart;static GkrellmMonitor *mon_mem, *mon_swap;static MeminfoMeter mem, swap;static MeminfoChart swap_chart;static gint x_scroll, x_mon_motion, x_moved, ascent;static MeminfoMeter *mon_in_motion;static void (*read_mem_data)();static void (*read_swap_data)();static gintsetup_meminfo_interface(void) { if (!read_mem_data && !_GK.client_mode && gkrellm_sys_mem_init()) { read_mem_data = gkrellm_sys_mem_read_data; read_swap_data = gkrellm_sys_swap_read_data; } return read_mem_data ? TRUE : FALSE; }voidgkrellm_mem_client_divert(void (*read_mem_func)(), void (*read_swap_func)()) { read_mem_data = read_mem_func; read_swap_data = read_swap_func; }voidgkrellm_mem_assign_data(guint64 total, guint64 used, guint64 free, guint64 shared, guint64 buffers, guint64 cached) { mem.total = total; mem.used = used; mem.free = free; mem.shared = shared; mem.buffers = buffers; mem.cached = cached; }voidgkrellm_swap_assign_data(guint64 total, guint64 used, gulong swap_in, gulong swap_out) { swap.total = total; swap.used = used; swap_chart.page_in = swap_in; swap_chart.page_out = swap_out; } /* Reading system memory data can be expensive, | so I do some dynamic adjustments on how often I do the updates. | I increase the update rate if system activity is detected. | This is an effort to get good meter response and to | not contribute to cpu chart activity during quiet times, ie maintain | a good S/N where I'm the noise. */#define PIPE_SIZE 3static gint mem_pipe[PIPE_SIZE], swap_pipe[PIPE_SIZE];static gint force_update = TRUE;gbooleanforce_meminfo_update(void) { gint i, force; force = force_update ? TRUE : FALSE; force_update = FALSE; if (GK.second_tick) { for (i = 1; i < PIPE_SIZE; ++i) if (mem_pipe[i] || swap_pipe[i]) force = TRUE; if (_GK.cpu_sys_activity > 3) force = TRUE; } return force; }static gintformat_meminfo_data(MeminfoMeter *mm, gchar *src_string, gchar *buf, gint size) { gulong t, u, f; gchar *s, *label; gint len; if (!buf || size < 1) return -1; --size; *buf = '\0'; if (!src_string) return -1; label = mm->label; t = MEG(mm->total); u = MEG(mm->used); f = t - u; for (s = src_string; *s != '\0' && size > 0; ++s) { len = 1; if (*s == '$' && *(s + 1) != '\0') { switch(*(s + 1)) { case 'l': len = snprintf(buf, size, "%s", label); break; case 't': len = snprintf(buf, size, "%ldM", t); break; case 'u': len = snprintf(buf, size, "%ldM", u); break; case 'U': if (t > 0) len = snprintf(buf, size, "%ld%%", 100 * u / t); break; case 'f': len = snprintf(buf, size, "%ldM", f); break; case 'F': if (t > 0) len = snprintf(buf, size, "%ld%%", 100 * f / t); break; case 's': if (mm == &mem) len = snprintf(buf, size, "%ldM", MEG(mem.shared)); break; case 'b': if (mm == &mem) len = snprintf(buf, size, "%ldM",MEG(mem.buffers)); break; case 'c': if (mm == &mem) len = snprintf(buf, size, "%ldM", MEG(mem.cached)); break; case 'H': len = snprintf(buf, size, "%s", gkrellm_sys_get_host_name()); break; default: *buf = *s; if (size > 1) { *(buf + 1) = *(s + 1); ++len; } break; } ++s; } else *buf = *s; size -= len; buf += len; } *buf = '\0'; return t + u + 1; /* A way to know if decal text changed. */ }static gintdraw_decal_label(MeminfoMeter *mm, gint draw_to_screen) { GkrellmDecal *d; GkrellmTextstyle ts_save; gchar buf[128]; gint x_off, w; d = mm->decal_label; if (! mm->label_is_data) { gkrellm_decal_text_set_offset(d, mm->x_label, 0); gkrellm_draw_decal_text(mm->panel, d, mm->label, 0); } else { ts_save = d->text_style; d->text_style = *gkrellm_meter_alt_textstyle(mm->style_id); format_meminfo_data(mm, mm->data_format_shadow, buf, sizeof(buf)); gkrellm_decal_scroll_text_set_markup(mm->panel, d, buf); gkrellm_decal_scroll_text_get_size(d, &w, NULL); if (w > d->w) x_off = d->w / 3 - x_scroll; else x_off = 0; gkrellm_decal_text_set_offset(d, x_off, 0); d->text_style = ts_save; } if (draw_to_screen) gkrellm_draw_panel_layers(mm->panel); return w; }static voidcb_command_process(GkrellmAlert *alert, gchar *src, gchar *dst, gint len, MeminfoMeter *m) { format_meminfo_data(m, src, dst, len); }static voidrecord_activity(gint *pipe, gint modified) { gint i; for (i = PIPE_SIZE - 1; i > 0; --i) pipe[i] = pipe[i-1]; pipe[0] = modified; }static GkrellmSizeAbbrev swap_blocks_abbrev[] = { { KB_SIZE(1), 1, "%.0f" }, { KB_SIZE(20), KB_SIZE(1), "%.1fK" }, { MB_SIZE(1), KB_SIZE(1), "%.0fK" }, { MB_SIZE(20), MB_SIZE(1), "%.1fM" } };static gchar *text_format, *text_format_locale;static voidformat_chart_text(MeminfoChart *mc, gchar *buf, gint size) { GkrellmChart *cp; gchar c, *s; size_t tbl_size; gint len, in_blocks, out_blocks, blocks; --size; *buf = '\0'; cp = mc->chart; in_blocks = gkrellm_get_current_chartdata(mc->in_cd); out_blocks = gkrellm_get_current_chartdata(mc->out_cd); tbl_size = sizeof(swap_blocks_abbrev) / sizeof(GkrellmSizeAbbrev); for (s = text_format_locale; *s != '\0' && size > 0; ++s) { len = 1; if (*s == '$' && *(s + 1) != '\0') { blocks = -1; if ((c = *(s + 1)) == 'T') blocks = in_blocks + out_blocks; else if (c == 'M') blocks = gkrellm_get_chart_scalemax(cp); else if (c == 'i') blocks = in_blocks; else if (c == 'o') blocks = out_blocks; else { *buf = *s; if (size > 1) { *(buf + 1) = *(s + 1); ++len; } } if (blocks >= 0) len = gkrellm_format_size_abbrev(buf, size, (gfloat) blocks, &swap_blocks_abbrev[0], tbl_size); ++s; } else *buf = *s; size -= len; buf += len; } *buf = '\0'; }static voiddraw_extra(MeminfoChart *mc) { gchar buf[128]; if (!mc->extra_info) return; format_chart_text(mc, buf, sizeof(buf)); gkrellm_draw_chart_text(mc->chart, DEFAULT_STYLE_ID, buf); /* XXX */ }static voidrefresh_chart(MeminfoChart *mc) { if (mc->chart) { gkrellm_draw_chartdata(mc->chart); draw_extra(mc); gkrellm_draw_chart_to_screen(mc->chart); } }static gintcb_extra(GtkWidget *widget, GdkEventButton *ev, gpointer data) { MeminfoChart *mc = (MeminfoChart *) data; if (ev->button == 1 && ev->type == GDK_BUTTON_PRESS) { mc->extra_info = !mc->extra_info; gkrellm_config_modified(); refresh_chart(mc); } else if ( ev->button == 3 || (ev->button == 1 && ev->type == GDK_2BUTTON_PRESS) ) gkrellm_chartconfig_window_create(mc->chart); return FALSE; }static voidupdate_meminfo(void) { GkrellmChart *cp; gulong u, b, c, used; gint w_scroll, w, full_scale; if (! (mem.enabled || swap.enabled || swap_chart.enabled)) return; if (GK.five_second_tick || force_meminfo_update()) (*read_mem_data)(); (*read_swap_data)(); if (GK.second_tick) { MeminfoChart *mc = &swap_chart; if ((cp = mc->chart) != NULL && GK.second_tick) { gkrellm_store_chartdata(cp, 0, mc->page_out, mc->page_in); refresh_chart(mc); } } if (mem.enabled) { full_scale = (gint) (mem.total >> 12); gkrellm_set_krell_full_scale(mem.krell_used, full_scale, 1); gkrellm_set_krell_full_scale(mem.krell_buffers, full_scale, 1); gkrellm_set_krell_full_scale(mem.krell_cache, full_scale, 1); used = u = (gulong) (mem.used >> 12); b = u + (gulong)(mem.buffers >> 12); c = b + (gulong)(mem.cached >> 12); if ( (mem.label_is_data && mon_in_motion && x_moved) || mem.mouse_entered ) u = b = c = 0; gkrellm_update_krell(mem.panel, mem.krell_used, u); gkrellm_update_krell(mem.panel, mem.krell_buffers, b); gkrellm_update_krell(mem.panel, mem.krell_cache, c); record_activity(mem_pipe, mem.krell_used->modified); if (mem.alert && GK.second_tick) gkrellm_check_alert(mem.alert, 100.0 * (gfloat) used / (gfloat) full_scale); } if (swap.enabled) { full_scale = (gint) (swap.total >> 12); gkrellm_set_krell_full_scale(swap.krell_used, full_scale, 1); used = u = (gulong)(swap.used >> 12); if ( (swap.label_is_data && mon_in_motion && x_moved) || swap.mouse_entered ) u = 0; gkrellm_update_krell(swap.panel, swap.krell_used, u); record_activity(swap_pipe, swap.krell_used->modified); if (swap.alert && GK.second_tick) gkrellm_check_alert(swap.alert, 100.0 * (gfloat) used / (gfloat) full_scale); } if (swap.krell_delta && swap.enabled) gkrellm_update_krell(swap.panel, swap.krell_delta, swap_chart.page_in + swap_chart.page_out); w = w_scroll = 0; if (mem.label_is_data && mon_in_motion != &mem && mem.enabled) w_scroll = draw_decal_label(&mem, 1); if (swap.label_is_data && mon_in_motion != &swap && swap.enabled) { if ((w = draw_decal_label(&swap, 1)) > w_scroll)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -