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