2 This file is part of GNUnet.
3 Copyright (C) 2008--2013 GNUnet e.V.
5 GNUnet is free software: you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published
7 by the Free Software Foundation, either version 3 of the License,
8 or (at your option) any later version.
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Affero General Public License for more details.
17 #include "gnunet_util_lib.h"
20 * File for parsing top-level /proc entities.
21 * Copyright Copyright (C) 1992-1998 by Michael K. Johnson, johnsonm@redhat.com
22 * Copyright 1998-2003 Albert Cahalan
23 * June 2003, Fabian Frederick, disk and slab info
25 * This library is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU Lesser General Public
27 * License as published by the Free Software Foundation; either
28 * version 2.1 of the License, or (at your option) any later version.
30 * This library is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
33 * Lesser General Public License for more details.
35 * You should have received a copy of the GNU Lesser General Public
36 * License along with this library; if not, write to the Free Software
37 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
40 #define BAD_OPEN_MESSAGE \
41 "Error: /proc must be mounted\n" \
42 " To mount /proc at boot you need an /etc/fstab line like:\n" \
43 " proc /proc proc defaults\n" \
44 " In the meantime, run \"mount proc /proc -t proc\"\n"
46 #define STAT_FILE "/proc/stat"
47 //static int stat_fd = -1;
48 #define UPTIME_FILE "/proc/uptime"
49 //static int uptime_fd = -1;
50 #define LOADAVG_FILE "/proc/loadavg"
51 //static int loadavg_fd = -1;
52 #define MEMINFO_FILE "/proc/meminfo"
53 static int meminfo_fd = -1;
54 #define VMINFO_FILE "/proc/vmstat"
55 //static int vminfo_fd = -1;
57 // As of 2.6.24 /proc/meminfo seems to need 888 on 64-bit,
58 // and would need 1258 if the obsolete fields were there.
59 static char buf[2048];
61 /* This macro opens filename only if necessary and seeks to 0 so
62 * that successive calls to the functions are more efficient.
63 * It also reads the current contents of the file into the global buf.
65 #define FILE_TO_BUF(filename, fd) do{ \
67 if (fd == -1 && (fd = open(filename, O_RDONLY)) == -1) { \
68 fputs(BAD_OPEN_MESSAGE, stderr); \
72 lseek(fd, 0L, SEEK_SET); \
73 if ((local_n = read(fd, buf, sizeof buf - 1)) < 0) { \
78 buf[local_n] = '\0'; \
82 /***********************************************************************/
84 * Copyright 1999 by Albert Cahalan; all rights reserved.
85 * This file may be used subject to the terms and conditions of the
86 * GNU Library General Public License Version 2, or any later version
87 * at your option, as published by the Free Software Foundation.
88 * This program is distributed in the hope that it will be useful,
89 * but WITHOUT ANY WARRANTY; without even the implied warranty of
90 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91 * GNU Library General Public License for more details.
94 typedef struct mem_table_struct {
95 const char *name; /* memory type name */
96 unsigned long *slot; /* slot in return struct */
99 static int compare_mem_table_structs(const void *a, const void *b){
100 return strcmp(((const mem_table_struct*)a)->name,((const mem_table_struct*)b)->name);
103 /* example data, following junk, with comments added:
105 * MemTotal: 61768 kB old
106 * MemFree: 1436 kB old
107 * MemShared: 0 kB old (now always zero; not calculated)
108 * Buffers: 1312 kB old
109 * Cached: 20932 kB old
110 * Active: 12464 kB new
111 * Inact_dirty: 7772 kB new
112 * Inact_clean: 2008 kB new
113 * Inact_target: 0 kB new
114 * Inact_laundry: 0 kB new, and might be missing too
119 * SwapTotal: 122580 kB old
120 * SwapFree: 60352 kB old
121 * Inactive: 20420 kB 2.5.41+
122 * Dirty: 0 kB 2.5.41+
123 * Writeback: 0 kB 2.5.41+
124 * Mapped: 9792 kB 2.5.41+
125 * Slab: 4564 kB 2.5.41+
126 * Committed_AS: 8440 kB 2.5.41+
127 * PageTables: 304 kB 2.5.41+
128 * ReverseMaps: 5738 2.5.41+
129 * SwapCached: 0 kB 2.5.??+
130 * HugePages_Total: 220 2.5.??+
131 * HugePages_Free: 138 2.5.??+
132 * Hugepagesize: 4096 kB 2.5.??+
136 unsigned long kb_main_shared;
137 /* old but still kicking -- the important stuff */
138 unsigned long kb_main_buffers;
139 unsigned long kb_main_cached;
140 unsigned long kb_main_free;
141 unsigned long kb_main_total;
142 unsigned long kb_swap_free;
143 unsigned long kb_swap_total;
144 /* recently introduced */
145 unsigned long kb_high_free;
146 unsigned long kb_high_total;
147 unsigned long kb_low_free;
148 unsigned long kb_low_total;
150 unsigned long kb_active;
151 unsigned long kb_inact_laundry;
152 unsigned long kb_inact_dirty;
153 unsigned long kb_inact_clean;
154 unsigned long kb_inact_target;
155 unsigned long kb_swap_cached; /* late 2.4 and 2.6+ only */
157 unsigned long kb_swap_used;
158 unsigned long kb_main_used;
160 unsigned long kb_writeback;
161 unsigned long kb_slab;
162 unsigned long nr_reversemaps;
163 unsigned long kb_committed_as;
164 unsigned long kb_dirty;
165 unsigned long kb_inactive;
166 unsigned long kb_mapped;
167 unsigned long kb_pagetables;
168 // seen on a 2.6.x kernel:
169 static unsigned long kb_vmalloc_chunk;
170 static unsigned long kb_vmalloc_total;
171 static unsigned long kb_vmalloc_used;
172 // seen on 2.6.24-rc6-git12
173 static unsigned long kb_anon_pages;
174 static unsigned long kb_bounce;
175 static unsigned long kb_commit_limit;
176 static unsigned long kb_nfs_unstable;
177 static unsigned long kb_swap_reclaimable;
178 static unsigned long kb_swap_unreclaimable;
181 char namebuf[16]; /* big enough to hold any row name */
182 mem_table_struct findme = { namebuf, NULL};
183 mem_table_struct *found;
186 static const mem_table_struct mem_table[] = {
187 {"Active", &kb_active}, // important
188 {"AnonPages", &kb_anon_pages},
189 {"Bounce", &kb_bounce},
190 {"Buffers", &kb_main_buffers}, // important
191 {"Cached", &kb_main_cached}, // important
192 {"CommitLimit", &kb_commit_limit},
193 {"Committed_AS", &kb_committed_as},
194 {"Dirty", &kb_dirty}, // kB version of vmstat nr_dirty
195 {"HighFree", &kb_high_free},
196 {"HighTotal", &kb_high_total},
197 {"Inact_clean", &kb_inact_clean},
198 {"Inact_dirty", &kb_inact_dirty},
199 {"Inact_laundry",&kb_inact_laundry},
200 {"Inact_target", &kb_inact_target},
201 {"Inactive", &kb_inactive}, // important
202 {"LowFree", &kb_low_free},
203 {"LowTotal", &kb_low_total},
204 {"Mapped", &kb_mapped}, // kB version of vmstat nr_mapped
205 {"MemFree", &kb_main_free}, // important
206 {"MemShared", &kb_main_shared}, // important, but now gone!
207 {"MemTotal", &kb_main_total}, // important
208 {"NFS_Unstable", &kb_nfs_unstable},
209 {"PageTables", &kb_pagetables}, // kB version of vmstat nr_page_table_pages
210 {"ReverseMaps", &nr_reversemaps}, // same as vmstat nr_page_table_pages
211 {"SReclaimable", &kb_swap_reclaimable}, // "swap reclaimable" (dentry and inode structures)
212 {"SUnreclaim", &kb_swap_unreclaimable},
213 {"Slab", &kb_slab}, // kB version of vmstat nr_slab
214 {"SwapCached", &kb_swap_cached},
215 {"SwapFree", &kb_swap_free}, // important
216 {"SwapTotal", &kb_swap_total}, // important
217 {"VmallocChunk", &kb_vmalloc_chunk},
218 {"VmallocTotal", &kb_vmalloc_total},
219 {"VmallocUsed", &kb_vmalloc_used},
220 {"Writeback", &kb_writeback}, // kB version of vmstat nr_writeback
222 const int mem_table_count = sizeof(mem_table)/sizeof(mem_table_struct);
224 FILE_TO_BUF(MEMINFO_FILE,meminfo_fd);
230 tail = strchr(head, ':');
233 if(strlen(head) >= sizeof(namebuf)){
237 strcpy(namebuf,head);
238 found = bsearch(&findme, mem_table, mem_table_count,
239 sizeof(mem_table_struct), compare_mem_table_structs
242 if(!found) goto nextline;
243 *(found->slot) = (unsigned long)strtoull(head,&tail,10);
245 tail = strchr(head, '\n');
249 if(!kb_low_total){ /* low==main except with large-memory support */
250 kb_low_total = kb_main_total;
251 kb_low_free = kb_main_free;
253 if(kb_inactive==~0UL){
254 kb_inactive = kb_inact_dirty + kb_inact_clean + kb_inact_laundry;
256 kb_swap_used = kb_swap_total - kb_swap_free;
257 kb_main_used = kb_main_total - kb_main_free;