OSDN Git Service

Revert "ksysguard: remove the memory leaking scan_one()"
[kde/kde-workspace.git] / ksysguard / ksysguardd / Linux / Memory.c
1 /*
2     KSysGuard, the KDE System Guard
3
4     Copyright (c) 1999 - 2001 Chris Schlaeger <cs@kde.org>
5
6     This program is free software; you can redistribute it and/or
7     modify it under the terms of version 2 of the GNU General Public
8     License as published by the Free Software Foundation.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
18
19 */
20
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28
29 #include "Command.h"
30 #include "ksysguardd.h"
31
32 #include "Memory.h"
33
34 #define MEMINFOBUFSIZE (2 * 1024)
35
36 static char MemInfoBuf[ MEMINFOBUFSIZE ];
37 static int Dirty = 1;
38
39 static unsigned long long Total = 0;
40 static unsigned long long MFree = 0;
41 static unsigned long long Appl = 0;
42 static unsigned long long Used = 0;
43 static unsigned long long Buffers = 0;
44 static unsigned long long Cached = 0;
45 static unsigned long long STotal = 0;
46 static unsigned long long SFree = 0;
47 static unsigned long long SUsed = 0;
48
49 static void scan_one( const char* buff, const char *key, unsigned long long* val )
50 {   
51   int o;
52   char *b = strstr( buff, key );
53   if ( b )  
54     o = sscanf( b + strlen( key ), ": %llu", val );
55 }
56
57 static void processMemInfo()
58 {
59   scan_one( MemInfoBuf, "MemTotal", &Total );
60   scan_one( MemInfoBuf, "MemFree", &MFree );
61   scan_one( MemInfoBuf, "Buffers", &Buffers );
62   scan_one( MemInfoBuf, "Cached", &Cached );
63   scan_one( MemInfoBuf, "SwapTotal", &STotal );
64   scan_one( MemInfoBuf, "SwapFree", &SFree );
65   Used = Total - MFree;
66   Appl = ( Used - ( Buffers + Cached ) );
67
68   if ( STotal == 0 ) /* no swap activated */
69     SUsed = 0;
70   else
71     SUsed = STotal - SFree;
72
73   Dirty = 0;
74 }
75
76 /*
77 ================================ public part =================================
78 */
79
80 void initMemory( struct SensorModul* sm )
81 {
82   /**
83     Make sure that /proc/meminfo exists and is readable. If not we do
84     not register any monitors for memory.
85    */
86   if ( updateMemory() < 0 )
87     return;
88
89   registerMonitor( "mem/physical/free", "integer", printMFree, printMFreeInfo, sm );
90   registerMonitor( "mem/physical/used", "integer", printUsed, printUsedInfo, sm );
91   registerMonitor( "mem/physical/application", "integer", printAppl, printApplInfo, sm );
92   registerMonitor( "mem/physical/buf", "integer", printBuffers, printBuffersInfo, sm );
93   registerMonitor( "mem/physical/cached", "integer", printCached, printCachedInfo, sm );
94   registerMonitor( "mem/swap/used", "integer", printSwapUsed, printSwapUsedInfo, sm );
95   registerMonitor( "mem/swap/free", "integer", printSwapFree, printSwapFreeInfo, sm );
96 }
97
98 void exitMemory( void )
99 {
100 }
101
102 int updateMemory( void )
103 {
104   /**
105     The amount of total and used memory is read from the /proc/meminfo.
106     It also contains the information about the swap space.
107     The 'file' looks like this:
108
109     MemTotal:       516560 kB
110     MemFree:          7812 kB
111     MemShared:           0 kB
112     Buffers:         80312 kB
113     Cached:         236432 kB
114     SwapCached:        468 kB
115     Active:         291992 kB
116     Inactive:       133556 kB
117     HighTotal:           0 kB
118     HighFree:            0 kB
119     LowTotal:       516560 kB
120     LowFree:          7812 kB
121     SwapTotal:      899632 kB
122     SwapFree:       898932 kB
123     Dirty:            2736 kB
124     Writeback:           0 kB
125     Mapped:         155996 kB
126     Slab:            73920 kB
127     Committed_AS:   315588 kB
128     PageTables:       1764 kB
129     ReverseMaps:    103458
130    */
131
132   int fd;
133   size_t n;
134
135   if ( ( fd = open( "/proc/meminfo", O_RDONLY ) ) < 0 ) {
136     print_error( "Cannot open \'/proc/meminfo\'!\n"
137                  "The kernel needs to be compiled with support\n"
138                  "for /proc file system enabled!\n" );
139     return -1;
140   }
141
142   n = read( fd, MemInfoBuf, MEMINFOBUFSIZE - 1 );
143   if ( n == MEMINFOBUFSIZE - 1 || n <= 0 ) {
144     log_error( "Internal buffer too small to read \'/proc/meminfo\'" );
145     close( fd );
146     return -1;
147   }
148
149   close( fd );
150   MemInfoBuf[ n ] = '\0';
151   Dirty = 1;
152
153   return 0;
154 }
155
156 void printMFree( const char* cmd )
157 {
158   (void)cmd;
159
160   if ( Dirty )
161     processMemInfo();
162
163   output( "%llu\n", MFree );
164 }
165
166 void printMFreeInfo( const char* cmd )
167 {
168   (void)cmd;
169
170   if ( Dirty )
171     processMemInfo();
172
173   output( "Free Memory\t0\t%llu\tKB\n", Total );
174 }
175
176 void printUsed( const char* cmd )
177 {
178   (void)cmd;
179
180   if ( Dirty )
181     processMemInfo();
182
183   output( "%llu\n", Used );
184 }
185
186 void printUsedInfo( const char* cmd )
187 {
188   (void)cmd;
189
190   if ( Dirty )
191     processMemInfo();
192
193   output( "Used Memory\t0\t%llu\tKB\n", Total );
194 }
195
196 void printAppl( const char* cmd )
197 {
198   (void)cmd;
199
200   if ( Dirty )
201     processMemInfo();
202
203   output( "%llu\n", Appl );
204 }
205
206 void printApplInfo( const char* cmd )
207 {
208   (void)cmd;
209
210   if ( Dirty )
211     processMemInfo();
212
213   output( "Application Memory\t0\t%llu\tKB\n", Total );
214 }
215
216 void printBuffers( const char* cmd )
217 {
218   (void)cmd;
219
220   if ( Dirty )
221     processMemInfo();
222
223   output( "%llu\n", Buffers );
224 }
225
226 void printBuffersInfo( const char* cmd )
227 {
228   (void)cmd;
229
230   if ( Dirty )
231     processMemInfo();
232
233   output( "Buffer Memory\t0\t%llu\tKB\n", Total );
234 }
235
236 void printCached( const char* cmd )
237 {
238   (void)cmd;
239
240   if ( Dirty )
241     processMemInfo();
242
243   output( "%llu\n", Cached );
244 }
245
246 void printCachedInfo( const char* cmd )
247 {
248   (void)cmd;
249
250   if ( Dirty )
251     processMemInfo();
252
253   output( "Cached Memory\t0\t%llu\tKB\n", Total );
254 }
255
256 void printSwapUsed( const char* cmd )
257 {
258   (void)cmd;
259
260   if ( Dirty )
261     processMemInfo();
262
263   output( "%llu\n", SUsed );
264 }
265
266 void printSwapUsedInfo( const char* cmd )
267 {
268   (void)cmd;
269
270   if ( Dirty )
271     processMemInfo();
272
273   output( "Used Swap Memory\t0\t%llu\tKB\n", STotal );
274 }
275
276 void printSwapFree( const char* cmd )
277 {
278   (void)cmd;
279
280   if ( Dirty )
281     processMemInfo();
282
283   output( "%llu\n", SFree );
284 }
285
286 void printSwapFreeInfo( const char* cmd )
287 {
288   (void)cmd;
289
290   if ( Dirty )
291     processMemInfo();
292
293   output( "Free Swap Memory\t0\t%llu\tKB\n", STotal );
294 }