This source file includes following definitions.
- get_loadavg
- get_uptime
- get_meminfo
- get_task
- get_phys_addr
- get_array
- get_env
- get_arg
- get_stat
- get_statm
- array_read
1
2
3
4
5
6
7
8
9
10 #include <linux/types.h>
11 #include <linux/errno.h>
12 #include <linux/sched.h>
13 #include <linux/kernel.h>
14 #include <linux/tty.h>
15
16 #include <asm/segment.h>
17 #include <asm/io.h>
18
19 #define LOAD_INT(x) ((x) >> FSHIFT)
20 #define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)
21
22 #define KSTK_EIP(stack) (((char *)stack)[1019])
23 #define KSTK_ESP(stack) (((char *)stack)[1022])
24
25 #define _SSIZE(stack) (TASK_SIZE - KSTK_ESP(stack))
26 #define SSIZE(stack) (KSTK_ESP(stack) ? _SSIZE(stack) : 0)
27
28 #define VSIZE(task,stack) ((task)->brk + 1023 + SSIZE(stack))
29 #define SIZE(task,stack) (((task)->brk - (task)->end_code + 1023 + \
30 SSIZE(stack)) / 1024)
31
32
33 static int get_loadavg(char * buffer)
34 {
35 int a, b, c;
36
37 a = avenrun[0] + (FIXED_1/200);
38 b = avenrun[1] + (FIXED_1/200);
39 c = avenrun[2] + (FIXED_1/200);
40 return sprintf(buffer,"%d.%02d %d.%02d %d.%02d\n",
41 LOAD_INT(a), LOAD_FRAC(a),
42 LOAD_INT(b), LOAD_FRAC(b),
43 LOAD_INT(c), LOAD_FRAC(c));
44 }
45
46 static int get_uptime(char * buffer)
47 {
48 return sprintf(buffer,"%d\n",(jiffies+jiffies_offset)/HZ);
49 }
50
51 static int get_meminfo(char * buffer)
52 {
53 struct sysinfo i;
54
55 si_meminfo(&i);
56 si_swapinfo(&i);
57 return sprintf(buffer, " total: used: free: shared: buffers:\n"
58 "Mem: %8d %8d %8d %8d %8d\n"
59 "Swap: %8d %8d %8d\n",
60 i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram,
61 i.totalswap, i.totalswap-i.freeswap, i.freeswap);
62 }
63
64 static struct task_struct ** get_task(pid_t pid)
65 {
66 struct task_struct ** p;
67
68 p = task;
69 while (++p < task+NR_TASKS) {
70 if (*p && (*p)->pid == pid)
71 return p;
72 }
73 return NULL;
74 }
75
76 static unsigned long get_phys_addr(struct task_struct ** p, unsigned long ptr)
77 {
78 unsigned long page;
79
80 if (!p || !*p || ptr >= TASK_SIZE)
81 return 0;
82 page = (*p)->tss.cr3;
83 page += (ptr >> 20) & 0xffc;
84 page = *(unsigned long *) page;
85 if (!(page & 1))
86 return 0;
87 page &= 0xfffff000;
88 page += (ptr >> 10) & 0xffc;
89 page = *(unsigned long *) page;
90 if (!(page & 1))
91 return 0;
92 page &= 0xfffff000;
93 page += ptr & 0xfff;
94 return page;
95 }
96
97 static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer)
98 {
99 unsigned long addr;
100 int size = 0, result = 0;
101 char c;
102
103 if (start >= end)
104 return result;
105 for (;;) {
106 addr = get_phys_addr(p, start);
107 if (!addr)
108 return result;
109 do {
110 c = *(char *) addr;
111 if (!c)
112 result = size;
113 if (size < PAGE_SIZE)
114 buffer[size++] = c;
115 else
116 return result;
117 addr++;
118 start++;
119 if (start >= end)
120 return result;
121 } while (!(addr & 0xfff));
122 }
123 }
124
125 static int get_env(int pid, char * buffer)
126 {
127 struct task_struct ** p = get_task(pid);
128
129 if (!p || !*p)
130 return 0;
131 return get_array(p, (*p)->env_start, (*p)->env_end, buffer);
132 }
133
134 static int get_arg(int pid, char * buffer)
135 {
136 struct task_struct ** p = get_task(pid);
137
138 if (!p || !*p)
139 return 0;
140 return get_array(p, (*p)->arg_start, (*p)->arg_end, buffer);
141 }
142
143 static int get_stat(int pid, char * buffer)
144 {
145 struct task_struct ** p = get_task(pid);
146 unsigned long sigignore=0, sigcatch=0, bit=1;
147 int i;
148 char state;
149
150 if (!p || !*p)
151 return 0;
152 if ((*p)->state < 0)
153 state = '.';
154 else
155 state = "RSDZTD"[(*p)->state];
156 for(i=0; i<32; ++i) {
157 switch((int) (*p)->sigaction[i].sa_handler) {
158 case 1: sigignore |= bit; break;
159 case 0: break;
160 default: sigcatch |= bit;
161 } bit <<= 1;
162 }
163 return sprintf(buffer,"%d (%s) %c %d %d %d %d %d %u %u \
164 %u %u %u %d %d %d %d %d %d %u %u %d %u %u %u %u %u %u %u %u %d \
165 %d %d %d %u\n",
166 pid,
167 (*p)->comm,
168 state,
169 (*p)->p_pptr->pid,
170 (*p)->pgrp,
171 (*p)->session,
172 (*p)->tty,
173 ((*p)->tty == -1) ? -1 :
174 tty_table[(*p)->tty]->pgrp,
175 (*p)->flags,
176 (*p)->min_flt,
177 (*p)->cmin_flt,
178 (*p)->maj_flt,
179 (*p)->cmaj_flt,
180 (*p)->utime,
181 (*p)->stime,
182 (*p)->cutime,
183 (*p)->cstime,
184 (*p)->counter,
185
186 (*p)->priority,
187
188 (*p)->timeout,
189 (*p)->it_real_value,
190 (*p)->start_time,
191 VSIZE((*p),(*p)->kernel_stack_page),
192 (*p)->rss,
193 (*p)->rlim[RLIMIT_RSS].rlim_cur,
194 (*p)->start_code,
195 (*p)->end_code,
196 (*p)->start_stack,
197 KSTK_ESP((*p)->kernel_stack_page),
198 KSTK_EIP((*p)->kernel_stack_page),
199 (*p)->signal,
200 (*p)->blocked,
201 sigignore,
202 sigcatch,
203 (*p)->tss.eip);
204 }
205
206 static int get_statm(int pid, char * buffer)
207 {
208 struct task_struct ** p = get_task(pid);
209 int i, tpag;
210 int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
211 unsigned long ptbl, *buf, *pte, *pagedir, map_nr;
212
213 if (!p || !*p)
214 return 0;
215 tpag = (*p)->end_code / PAGE_SIZE;
216 if ((*p)->state != TASK_ZOMBIE) {
217 pagedir = (void *)((*p)->tss.cr3 + ((*p)->start_code >> 20));
218 for (i = 0; i < 0x300; ++i) {
219 if ((ptbl = pagedir[i]) == 0) {
220 tpag -= 1024;
221 continue;
222 }
223 buf = (void *)(ptbl & 0xfffff000);
224 for (pte = buf; pte < (buf + 1024); ++pte) {
225 if (*pte != 0) {
226 ++size;
227 if (*pte & 1) {
228 ++resident;
229 if (tpag > 0)
230 ++trs;
231 else
232 ++drs;
233 if (i >= 15 && i < 0x2f0) {
234 ++lrs;
235 if (*pte & 0x40)
236 ++dt;
237 else
238 --drs;
239 }
240 map_nr = MAP_NR(*pte);
241 if (map_nr < (high_memory / 4096) && mem_map[map_nr] > 1)
242 ++share;
243 }
244 }
245 --tpag;
246 }
247 }
248 }
249 return sprintf(buffer,"%d %d %d %d %d %d %d\n",
250 size, resident, share, trs, lrs, drs, dt);
251 }
252
253 static int array_read(struct inode * inode, struct file * file,char * buf, int count)
254 {
255 char * page;
256 int length;
257 int end;
258 int type, pid;
259
260 if (count < 0)
261 return -EINVAL;
262 page = (char *) get_free_page(GFP_KERNEL);
263 if (!page)
264 return -ENOMEM;
265 type = inode->i_ino;
266 pid = type >> 16;
267 type &= 0x0000ffff;
268 switch (type) {
269 case 2:
270 length = get_loadavg(page);
271 break;
272 case 3:
273 length = get_uptime(page);
274 break;
275 case 4:
276 length = get_meminfo(page);
277 break;
278 case 9:
279 length = get_env(pid, page);
280 break;
281 case 10:
282 length = get_arg(pid, page);
283 break;
284 case 11:
285 length = get_stat(pid, page);
286 break;
287 case 12:
288 length = get_statm(pid, page);
289 break;
290 default:
291 free_page((unsigned long) page);
292 return -EBADF;
293 }
294 if (file->f_pos >= length) {
295 free_page((unsigned long) page);
296 return 0;
297 }
298 if (count + file->f_pos > length)
299 count = length - file->f_pos;
300 end = count + file->f_pos;
301 memcpy_tofs(buf, page + file->f_pos, count);
302 free_page((unsigned long) page);
303 file->f_pos = end;
304 return count;
305 }
306
307 static struct file_operations proc_array_operations = {
308 NULL,
309 array_read,
310 NULL,
311 NULL,
312 NULL,
313 NULL,
314 NULL,
315 NULL,
316 NULL
317 };
318
319 struct inode_operations proc_array_inode_operations = {
320 &proc_array_operations,
321 NULL,
322 NULL,
323 NULL,
324 NULL,
325 NULL,
326 NULL,
327 NULL,
328 NULL,
329 NULL,
330 NULL,
331 NULL,
332 NULL,
333 NULL
334 };