源程序附最后(也可直接打包下载http://download.csdn.net/detail/creazyapple/4088149)
要求:
理解和分析/proc文件
内容
了解/proc文件的特点和使用方法。
监控系统状态,显示系统中若干部件的使用情况。用图形界面显示系统监控状态。
相关原理:
用户和应用程序可以通过/proc得到系统的信息,并可以改变内核的某些参数。由于系统的信息是动态改变的,所以用户或应用程序读取proc文件时,proc文件系统是动态从系统内核读出所需信息并提交的。
我们要显示系统信息,只需进行相应的文件操作。首先打开相应的文件,读取所需要的信息,将其写入一个缓冲区中,然后将缓冲区的内容加到Gtk的相应的控件上面去,最后将控件组合显示即可。
/proc/文件结构参考:http://blog.csdn.net/ubuntulover/article/details/4449787
比如我们如果要读取cpu信息,可以在控制台下输入命令:cat /proc/cpuinf
要得到内存信息,可以输入命令:cat /proc/meminfo
这只是冰山一角,仅此我们已经看到/proc目录下文件内容之丰富。
要想编程读取这些信息,首先我们要了解/proc结构,了解其各种信息的排布,然后就像读普通文件一样将其筛选出来。
比如,查看系统的cpu频率,属于cpu信息:more /proc/cpuinfo (注,命令more 和cat功能相似,都是显示一个文件的内容)
其排布为如下:
我们也就知道,cpuinf文件中,一种信息放一行,因此我们一行一行的遴选信息。
首先需将cpuinf文件读出来,
fp = fopen("/proc/cpuinf", "r");
/* 从fp中读取sizeof(buffer)块数据放入buffer */
buf = fread(buffer, 1, sizeof(buffer), fp);
fclose(fp);
然后进行字符串匹配,找到含有“cpu MHz”这个字符串的一行,读出来即可。
其它如模块信息、内存信息,类似处理,字要你了解了其结构,就可以方便的读出来
所以关键有3点:1、你知道信息在哪里;2、你看到了信息的排列方式;3、设计算法剔除无用信息。
而对于进程信息,稍复杂。
我们先看看进程信息放在哪里的:首先进入 /proc 目录并查看该目录下的文件:
蓝色的是目录(所谓的文件夹),绿色的是文件,文件中有cpuinf、meminfo等,我们之前已经看过。现在看看那些蓝色的以数字为名的文件夹,他们正是保存进程信息的!
目录1存储的是PID为1的进程的信息,目录2存储的是PID为2的进程的信息……
我们试着进入这些目录看看!
里面有一些目录和文件,其中有个status文件,打开看看:
看到了吧,很清晰地罗列出了进程1的信息,名字是init,状态Sleeping ,PID是1……
由此得知,要读取所有进程的信息列表,我们需要循环打开/proc文件夹下所有以数字命名的目录。
大致过程为:
while ((ptr = readdir(dir)) != NULL)
{
if ((ptr->d_name[0] >= '0') && (ptr->d_name[0] <= '9')) //打开以数值命名的目录
{
sprintf(path, "/proc/%s/status", ptr->d_name); //将此文件的全部路径写入name中
//打开这个文件,并且从中读取到有用的信息放在相应的数组中
fd = open(path, O_RDONLY);
read(fd, store, sizeof(store));
……
读取信息
……
close(fd);
}
}
closedir(dir);
好了,现在弄清楚了原理,就可以动手实现了。但是需要一个界面呀,这里我们继续用GTK来画界面。
关于GTK这里就不多说了。
最后实现界面截图:
杀死进程:
刷新列表:
最后,附上源程序。共11个文件,将其放入一个文件夹下,编译命令:gcc -o sb *.c `pkg-config --cflags --libs gtk+-2.0`(当然首先得配置好了GTK,
参考上一篇博客 ubuntu GTK+eclipse 配置 http://blog.csdn.net/creazyapple/article/details/7290443)
/*
* MainWin.c
* SystemMonitor
* Created on: 2012-2-24
* Author: zhushengben
*/
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <fcntl.h>
#include <dirent.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
#include <cairo.h>
#include <time.h>
#define MAX 1024
#include "searchInfor.h"
#include "cpu.h"
#include "memory.h"
#include "module.h"
#include "process.h"
#include "menuBar.h"
#include "progressBar.h"
#include "showAbout.h"
#include "refresh.h"
#include "showImage.h"
int main(int argc, char ** argv)
{
GtkWidget * window;
GtkWidget * main_vbox;
GtkWidget *tooltip;
gtk_init(&argc, &argv);
/* 主窗口 */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
tooltip = gtk_tooltips_new();
gtk_tooltips_set_tip(tooltip, window, "系统监视器\n此软件归华中科技大学所有\n未经授权不可擅自更改",
NULL);
gtk_window_set_title(GTK_WINDOW(window), "System Moniter");
gtk_window_set_opacity(GTK_WINDOW(window), 0.95); // 设置透明度函数
//update_widget_bg(window, BACK_IMAGE);
/* 默认窗口大小 */
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);
/* 窗口初始位置在屏幕最中央 */
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
/* 显示窗口 */
gtk_widget_show(window);
/* 创建一个纵向盒 */
main_vbox = gtk_vbox_new(FALSE, 10);
/* 设定这个容器和周围的间距 */
gtk_container_set_border_width(GTK_CONTAINER(main_vbox), 5);
/* 将这个布局容器添加到整个视窗的容器中 */
gtk_container_add(GTK_CONTAINER(window), main_vbox);
/* 显示该盒 */
gtk_widget_show(main_vbox);
createMenuBar(main_vbox);
/* 建立多标签页notebook */
GtkWidget *notebook = gtk_notebook_new();
gtk_notebook_set_tab_pos((GtkNotebook *) notebook, GTK_POS_BOTTOM);
gtk_notebook_set_show_border((GtkNotebook *) notebook, FALSE);
/* 在纵向盒顶部添加该笔记本 */
gtk_box_pack_end(GTK_BOX(main_vbox), notebook, TRUE, TRUE, 0);
/* 显示该笔记本 */
gtk_widget_show(notebook);
/* 新建第一个标签页到notebook,用的是frame框架 */
createCPUPage(notebook);
/* 新建第三个标签页到notebook */
createModPage(notebook);
/* 新建第四个标签页到notebook */
createProPage(notebook);
/* 新建第五个标签页到notebook */
/* 原来是mem模块在死循环中 */
createMemPage(notebook);
/* 新建第二个标签页到notebook */
createAboutPage(notebook);
gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook), 0);
/**************************************************/
gtk_timeout_add(400, refresh, pdata);
gtk_main();
return 0;
}
/*
* cpu.h
* helloWorld
* Created on: 2012-2-19
* Author: zhushengben
*/
#ifndef CPU_H_
#define CPU_H_
GtkWidget *window;
GtkWidget *main_vbox;
GtkWidget *clist; //进程时候需要的列表
GtkWidget *clist2; //模块读取时需要的列表
GtkWidget *cpu_draw_area;
GdkPixmap *cpu_graph;
GtkWidget *pbar_cpu;
/* 全局变量 */
static gint cpuPoints[100];
static gfloat cpu_rate = 0.0;
static char PID[20];
static int selectedRow;
float zuser = 0, ztotal = 0;
typedef struct CPUinfo
{
char modeName[50]; //line 5
char cpuMHz[10]; //line 7
char cacheSize[10];//line 8
char cpuCores[10]; //line 12
char addrSize[50]; //line 30
}*cpuInfo;
static gboolean cpu_expose_event(GtkWidget *widget, GdkEventExpose *event,
gpointer data)
{
gdk_draw_drawable(widget->window, widget->style->fg_gc[GTK_WIDGET_STATE(
widget)], cpu_graph, event->area.x, event->area.y, event->area.x,
event->area.y, event->area.width, event->area.height);
return FALSE;
}
static gboolean cpu_configure_event(GtkWidget *widget,
GdkEventConfigure *event, gpointer data)
{
if (cpu_graph)
{
g_object_unref(cpu_graph);
}
cpu_graph = gdk_pixmap_new(widget->window, widget->allocation.width,
widget->allocation.height, -1);
gdk_draw_rectangle(cpu_graph, widget->style->white_gc, TRUE, 0, 0,
widget->allocation.width, widget->allocation.height);
return TRUE;
}
/* 取得cpu利用率 */
float getCpuUseRatio()
{
FILE *fp;
char buffer[1024];
size_t buf;
float useRatio;
/* 分别为用户模式,低优先级用户模式,内核模式,空闲的处理器时间 */
float user = 0, nice = 0, sys = 0, idle = 0, iowait = 0;
fp = fopen("/proc/stat", "r");
/* 从fp中读取sizeof(buffer)块数据放入buffer,每次读一块 */
buf = fread(buffer, 1, sizeof(buffer), fp);
fclose(fp);
if (buf == 0)
return 0;
buffer[buf] == '\0';
sscanf(buffer, "cpu %f %f %f %f %f", &user, &nice, &sys, &idle, &iowait);
if (idle <= 0)
idle = 0;
useRatio = 100 * (user - zuser) / (user + nice + sys + idle - ztotal);
if (useRatio > 100)
useRatio = 100;
ztotal = user + nice + sys + idle;
zuser = user;
cpu_rate = useRatio;
return useRatio;
}
/* cpu标签页,显示cpu信息 */
void createCPUPage(GtkWidget* notebook)
{
GtkWidget *label;
GtkWidget *vbox;
GtkWidget *frame1 = gtk_frame_new("");
gtk_container_set_border_width(GTK_CONTAINER(frame1), 10);
gtk_widget_set_size_request(frame1, 120, 500);
gtk_widget_show(frame1);
/* 将该标签页加入到notebook中 */
gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame1, gtk_label_new(
"CPU信息"));
/* 在该页建议个表格,分为上下2行,一列 */
GtkWidget *table1 = gtk_table_new(10, 10, TRUE);
/* 将这个表添加到“cpu使用率“页 */
gtk_container_add(GTK_CONTAINER(frame1), table1);
/* 新建一个frame框架用于显示图表 */
GtkWidget *CPU_frame1 = gtk_frame_new("CPU使用历史曲线");
/* 放到表格第一行 */
/* 这个函数的参数不懂,不好调整 */
gtk_table_attach_defaults(GTK_TABLE(table1), CPU_frame1, 0, 8, 0, 5);
gtk_widget_show(CPU_frame1);
/* 现在,我们开始向屏幕绘图。
* 我们使用的构件是绘图区构件。
*一个绘图区构件本质上是一个 X 窗口,没有其它的东西。
*它是一个空白的画布,我们可以在其上绘制需要的东西。*/
cpu_draw_area = gtk_drawing_area_new();
/* 设置可以画图 */
gtk_widget_set_app_paintable(cpu_draw_area, TRUE);
/* 画图区默认大小 */
gtk_drawing_area_size(GTK_DRAWING_AREA(cpu_draw_area), 40, 80);
/* 画布添加到cpu曲线框架中 */
gtk_container_add(GTK_CONTAINER(CPU_frame1), cpu_draw_area);
gtk_widget_show(cpu_draw_area);
/* 关联回调函数 */
/* 关于各种事件不甚了解 */
g_signal_connect(cpu_draw_area, "expose_event",
G_CALLBACK(cpu_expose_event), NULL);
g_signal_connect(cpu_draw_area, "configure_event", G_CALLBACK(
cpu_configure_event), NULL);
gtk_widget_show(cpu_draw_area);
int i;
for (i = 0; i < 100; i++)
{
/* 要取[a,b)之间的随机整数(包括a,但不包括b),使用:
* (rand() % (b - a)) + a */
cpuPoints[i] = (rand() % 30 + 180);
}
// 此处出现问题
/* 不断刷新画图 */
// gtk_timeout_add(100, (GtkFunction) drawGraph, NULL);
/* 取得CPU信息 */
char modeName[50], cpuMHz[20], cacheSize[20], cpuCores[20], addrSize[50];
char cpuBuffer[1000];
//getCPUInfo("/proc/cpuinfo", modeName, cacheSize);
//cpuMHz,cacheSize,cpuCores,addrSize);
/* 不能用\t !! */
getInforNotd("/proc/cpuinfo", "model name", modeName);
getInforNotd("/proc/cpuinfo", "cache size", cacheSize);
getInforNotd("/proc/cpuinfo", "cpu MHz", cpuMHz);
getInforNotd("/proc/cpuinfo", "cpu cores", cpuCores);
getInforNotd("/proc/cpuinfo", "address sizes", addrSize);
/* 建一个frame在表一下半部显示cpu信息 */
GtkWidget *frame_down = gtk_frame_new("系统信息 ");
gtk_table_attach_defaults(GTK_TABLE(table1), frame_down, 0, 10, 5, 10);
gtk_widget_show(frame_down);
/* 这里必须要show表,为什么?不知到该在什么时候show什么 */
gtk_widget_show(table1);
/* 在该狂建建一个表格,将下半部分为1行,2列 *