/home/fernape/Projects/lkmonitor/src/procupdate.c

Go to the documentation of this file.
00001 
00002 /*
00003         lkmonitor (Linux Kernel Monitor)
00004 
00005         Application for monitoring and tuning a Linux kernel.
00006 
00007         Copyright (C) 2005-2008  Fernando ApesteguĂ­a
00008 
00009         This program is free software; you can redistribute it and/or
00010         modify it under the terms of the GNU General Public License
00011         as published by the Free Software Foundation; either version 2
00012         of the License, or (at your option) any later version.
00013 
00014         This program is distributed in the hope that it will be useful,
00015         but WITHOUT ANY WARRANTY; without even the implied warranty of
00016         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017         GNU General Public License for more details.
00018 
00019         You should have received a copy of the GNU General Public License
00020         along with this program; if not, write to the Free Software
00021         Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
00022 */
00023 
00024 /* 
00025  * Process specific information file
00026 */
00027 
00028 #ifdef HAVE_CONFIG_H
00029 #  include <config.h>
00030 #endif
00031 
00032 #include <glib.h>
00033 #include <gtk/gtk.h>
00034 #include <gnome.h>
00035 #include <dirent.h>
00036 #include <sys/stat.h>
00037 #include <sys/types.h>
00038 #include <unistd.h>
00039 #include "lkmonitor.h"
00040 #include "procinfo.h"
00041 #include "support.h"
00042 
00043 
00044 
00045 
00050 static void treeviews_construct(GtkWindow *window)
00051 {
00052         g_assert(window!=NULL);
00053 
00054   GtkTreeView *tv;
00055   GtkTreeView *tv_files;
00056   GtkListStore *ls;
00057   GtkListStore *ls_files;
00058   GtkCellRenderer *cr;
00059   GtkCellRenderer *cr_files;
00060 
00061   
00062   /* For Memory maps */  
00063                                              
00064   tv= GTK_TREE_VIEW(lookup_widget(GTK_WIDGET(window),"tv_maps"));
00065   ls=gtk_list_store_new(6,G_TYPE_STRING, G_TYPE_STRING,G_TYPE_STRING,
00066                         G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING);
00067   
00068   gtk_tree_view_set_model(GTK_TREE_VIEW(tv),GTK_TREE_MODEL(ls));
00069  
00070   /*First column*/
00071   cr = gtk_cell_renderer_text_new ();
00072   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
00073                                                -1,      
00074                                                _("Address"),  
00075                                                cr,
00076                                                "text", 0,
00077                                                NULL);
00078 
00079   /*Second column*/
00080 
00081   cr = gtk_cell_renderer_text_new ();
00082   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
00083                                                -1,      
00084                                                _("Flags"),  
00085                                                cr,
00086                                                "text", 1,
00087                                                NULL); 
00088 
00089   /*Third column*/
00090   cr = gtk_cell_renderer_text_new ();
00091   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
00092                                                -1,      
00093                                                _("Size"),  
00094                                                cr,
00095                                                "text", 2,
00096                                                NULL);
00097 
00098   /*Forth column*/
00099 
00100   cr = gtk_cell_renderer_text_new ();
00101   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
00102                                                -1,      
00103                                                _("Device"),  
00104                                                cr,
00105                                                "text", 3,
00106                                                NULL); 
00107 
00108   /*Fifth column*/
00109 
00110   cr = gtk_cell_renderer_text_new ();
00111   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
00112                                                -1,      
00113                                                _("Inode"),  
00114                                                cr,
00115                                                "text", 4,
00116                                                NULL); 
00117   
00118   /*Sixth column*/
00119 
00120   cr = gtk_cell_renderer_text_new ();
00121   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv),
00122                                                -1,      
00123                                                _("Object"),  
00124                                                cr,
00125                                                "text",5,
00126                                                NULL); 
00127 
00128   /* For files */  
00129                                              
00130   tv_files= (GtkTreeView *)lookup_widget(GTK_WIDGET(window),"tv_files");
00131   ls_files=gtk_list_store_new(3,G_TYPE_STRING, G_TYPE_STRING,G_TYPE_STRING);
00132   
00133   gtk_tree_view_set_model(GTK_TREE_VIEW(tv_files),GTK_TREE_MODEL(ls_files));
00134  
00135   /*First column*/
00136   cr_files = gtk_cell_renderer_text_new ();
00137   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv_files),
00138                                                -1,      
00139                                                _("FD"),  
00140                                                cr_files,
00141                                                "text", 0,
00142                                                NULL);
00143 
00144   /*Second column*/
00145 
00146   cr_files = gtk_cell_renderer_text_new ();
00147   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv_files),
00148                                                -1,      
00149                                                _("Type"),  
00150                                                cr_files,
00151                                                "text", 1,
00152                                                NULL); 
00153 
00154   /*Third column*/
00155 
00156   cr_files = gtk_cell_renderer_text_new ();
00157   gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (tv_files),
00158                                                -1,      
00159                                                _("Object"),  
00160                                                cr_files,
00161                                                "text", 2,
00162                                                NULL); 
00163 }
00164 
00165 
00171 static int gtktextbuffers_construct(GtkWindow *window)
00172 {
00173         g_assert(window!=NULL);
00174 
00175         GtkTextView *gtv;
00176         GtkTextBuffer *gtktextb;
00177 
00178         /* First, create the GtkTextBuffers */
00179 
00180         gtktextb=gtk_text_buffer_new(NULL);
00181 
00182         /* Attach them */
00183         gtv=GTK_TEXT_VIEW(lookup_widget(GTK_WIDGET(window),"textv_environ"));
00184         gtk_text_view_set_buffer(gtv,gtktextb);
00185 
00186         return 0;
00187 }
00188 
00189 
00195 void update_memory_maps(GtkTreeView *gtv,char *maps)
00196 {
00197 
00198   GtkTreeIter iter;
00199   GtkListStore *model;
00200   char *pointer;
00201   //char address[24],flags[4],size[10],dev[8],inode[16],object[200];
00202   /* --FIXME: Sizes for teh variables... */
00203   char address[100],flags[100],size[100],dev[100],inode[100],object[200];
00204 
00205   model=GTK_LIST_STORE(gtk_tree_view_get_model(gtv)); 
00206   
00207   pointer=maps;
00208 
00209   while(*pointer!='\0'){
00210         gtk_list_store_append(model,&iter);
00211         sscanf(pointer,"%s %s %s %s %s %s",address,flags,size,dev,inode,object);
00212         gtk_list_store_set(model,&iter,0,address,1,flags,2,size,3,dev,4,
00213                                 inode,5,object,-1);
00214         pointer=strchr(pointer,'\n')+1;
00215   }
00216 
00217 }
00218 
00223 static void link_get_name(char *path, GString *gs)
00224 {
00225 
00226 #define UNK_STR _("Unknown")
00227         char buf[50];
00228         int numchars;
00229 
00230         if((numchars=readlink(path, buf, sizeof(buf)))!=-1){
00231                 /* readlink doesn't include '\0' at the end */
00232                 *(buf+numchars)='\0';
00233                 g_string_printf(gs,"%s",buf);
00234         }else{
00235                 g_string_printf(gs,"%s",UNK_STR);
00236         }
00237 
00238 }
00239 
00240 
00247 static void get_type_by_fd(GString *gs,GString *gs_additional,mode_t mode,char *path)
00248 {
00249 
00250  if(S_ISREG(mode)){
00251         g_string_printf(gs,_("Regular file"));
00252         return;
00253  }
00254 
00255  if(S_ISDIR(mode)){
00256         g_string_printf(gs,_("Directory"));
00257         return;
00258  }
00259 
00260  if(S_ISCHR(mode)){
00261         g_string_printf(gs,_("Character Device"));
00262         link_get_name(path,gs_additional);
00263         return;
00264  }
00265 
00266  if(S_ISBLK(mode)){
00267         g_string_printf(gs,_("Block Device"));
00268         link_get_name(path,gs_additional);
00269         return;
00270  }
00271 
00272  if(S_ISFIFO(mode)){
00273         g_string_printf(gs,_("Fifo"));
00274         link_get_name(path,gs_additional);
00275         return;
00276  }
00277 
00278  if(S_ISLNK(mode)){
00279         g_string_printf(gs,_("Symbolic link"));
00280         link_get_name(path,gs_additional);
00281         return;
00282  }
00283 
00284  if(S_ISSOCK(mode)){
00285         g_string_printf(gs,_("Socket"));
00286         link_get_name(path,gs_additional);
00287         return;
00288  }
00289 
00290 }
00291 
00292 
00299 void update_fd_info(int pid,GtkTreeView *gtv,struct dirent **file_list,int numfiles)
00300 {
00301 
00302 #define UNK_STR _("Unknown")
00303         int i;
00304         GtkTreeIter iter;
00305         GtkListStore *model;
00306         GString *path;
00307         GString *type;
00308         GString *object;
00309         struct stat file_info;
00310 
00311         /* Initialize the GStrings */
00312    path=g_string_new("");
00313    type=g_string_new("");
00314    object=g_string_new("");
00315 
00316         /* Take the model */
00317         model=GTK_LIST_STORE(gtk_tree_view_get_model(gtv)); 
00318 
00319         /* For every file, get some information */
00320         for(i=0;i<numfiles;i++){
00321                 g_string_printf(path,"/proc/%d/fd/%s",pid,file_list[i]->d_name);
00322                 if(stat(path->str,&file_info)){
00323                         /* Put here default values */
00324                         g_string_printf(type,"%s",UNK_STR);
00325                         g_string_printf(object,"%s",UNK_STR);
00326                 }else{
00327                         /* We got information for the file */
00328                         get_type_by_fd(type,object,file_info.st_mode,path->str);
00329                 }
00330 
00331                 gtk_list_store_append(model,&iter);
00332                 gtk_list_store_set(model,&iter,0,file_list[i]->d_name,1,type->str,2,object->str,-1);
00333 
00334         }
00335 
00336 
00337         /* Free the dirent data structures and the list itself 
00338          * only in case the list has been filled some time before
00339          */
00340         if(numfiles!=-1){
00341                 int i;
00342                 for(i=0;i<numfiles;i++)
00343                         free(file_list[i]);
00344 
00345                 free(file_list);
00346         }
00347 
00348         /* Freeing GStrings */
00349         g_string_free(path,TRUE);
00350         g_string_free(type,TRUE);
00351         g_string_free(object,TRUE);
00352 
00353 }
00354 
00360 void update_mm_details(char *mmregion, GtkWindow *window,int pid)
00361 {
00362         struct mm_details details;
00363         GtkLabel *lbl;
00364         GString *gs=g_string_new("");
00365 
00366         get_mm_details(pid,&details,mmregion);
00367 
00368         /* Update the widgets */
00369         lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_size"));
00370         gtk_label_set_text(lbl,details.size);
00371         lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_rss"));
00372         gtk_label_set_text(lbl,details.rss);
00373         lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_shared"));
00374         g_string_printf(gs,"%s / %s",details.sh_clean,details.sh_dirty);
00375         gtk_label_set_text(lbl,gs->str);
00376         lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_private"));
00377         g_string_printf(gs,"%s / %s",details.priv_clean,details.priv_dirty);
00378         gtk_label_set_text(lbl,gs->str);
00379 
00380 
00381         /* Cleaning up */
00382         g_string_free(gs,TRUE);
00383 }
00384 
00390 void update_process_window(int pid, char *name,GtkWindow *window)
00391 {
00392         g_assert(pid>0 && name!=NULL && window!=NULL);
00393 
00394   struct procinfo pi;
00395   struct dirent **file_list;
00396   int numfiles;
00397 
00398   /* Construct the GtkTreeView for memory maps */
00399   treeviews_construct(window);
00400   gtktextbuffers_construct(window);
00401   
00402   /* Put the window title */
00403   {
00404         /* Construct the title */
00405         GString *title=g_string_new("");
00406         g_string_printf(title,"%s (PID: %d)",name,pid);
00407 
00408         gtk_window_set_title(window,title->str);
00409 
00410         /* Free things in this block */
00411         g_string_free(title,TRUE);
00412   }
00413 
00414   /* Get Process information */
00415   get_process_info(pid,&pi,&file_list,&numfiles);
00416   /* Display data */
00417 
00418   /*
00419    * NOTICE: This is inside the global gdk lock cause this is call from a
00420    * callback associated to a double click event.
00421    * So we don't need gdk_threads_enter/gdk_threads_leave
00422   */
00423 
00424   /* Command line */
00425   {
00426         GtkLabel *lbl;
00427         lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_cmdline"));
00428         gtk_label_set_text(lbl,pi.cmdline->str);
00429   }
00430 
00431   /* Environment variables */
00432   {
00433         GtkTextBuffer *gtb;
00434         GtkTextView *gtv;
00435         gtv=GTK_TEXT_VIEW(lookup_widget(GTK_WIDGET(window),"textv_environ"));
00436         gtb=gtk_text_view_get_buffer(gtv);
00437         gtk_text_buffer_set_text(gtb,pi.env->str,pi.env->len);
00438   }
00439 
00440   /* Memory maps */
00441   {
00442         GtkTreeView *gtv_mmaps;
00443         gtv_mmaps=GTK_TREE_VIEW(lookup_widget(GTK_WIDGET(window),"tv_maps"));
00444         update_memory_maps(gtv_mmaps,pi.maps->str);
00445   }
00446 
00447         /* Opened files */
00448         {
00449                 GtkTreeView *gtv_fd;
00450                 GtkLabel *lbl;
00451                 gtv_fd=GTK_TREE_VIEW(lookup_widget(GTK_WIDGET(window),"tv_files"));
00452                 update_fd_info(pid,gtv_fd,file_list,numfiles);
00453 
00454                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_files"));
00455                 if(numfiles!=-1)
00456                         gtk_label_set_text(lbl,(gchar *)lkmonitor_itoa(numfiles));
00457                 else
00458                         gtk_label_set_text(lbl,"No info.");
00459                 /* 
00460                  * The file_list structure and associated data are
00461                  * freed in the update_fd_info function
00462                 */
00463         }
00464 
00465         /* VM info and other status file bits... */
00466         {
00467                 GtkLabel *lbl;
00468 
00469                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmsize"));
00470                 gtk_label_set_text(lbl,pi.size);
00471                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmlocked"));
00472                 gtk_label_set_text(lbl,pi.locked);
00473                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmrss"));
00474                 gtk_label_set_text(lbl,pi.rss);
00475                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmdata"));
00476                 gtk_label_set_text(lbl,pi.data);
00477                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmstack"));
00478                 gtk_label_set_text(lbl,pi.stack);
00479                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmexecutable"));
00480                 gtk_label_set_text(lbl,pi.exe);
00481                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_vmlibraries"));
00482                 gtk_label_set_text(lbl,pi.lib);
00483                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_state"));
00484                 gtk_label_set_text(lbl,pi.state);
00485                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_sleepavg"));
00486                 gtk_label_set_text(lbl,pi.sleepavg);
00487                 lbl=GTK_LABEL(lookup_widget(GTK_WIDGET(window),"lbl_threads"));
00488                 gtk_label_set_text(lbl,pi.threads);
00489         
00490         }
00491 
00492 }

Generated on Tue Apr 1 22:52:52 2008 for lkmonitor by  doxygen 1.5.1