array.c
来自「elinux jffs初始版本 具体了解JFFS的文件系统!」· C语言 代码 · 共 1,284 行 · 第 1/3 页
C
1,284 行
/* * linux/fs/proc/array.c * * Copyright (C) 1992 by Linus Torvalds * based on ideas by Darren Senn * * Fixes: * Michael. K. Johnson: stat,statm extensions. * <johnsonm@stolaf.edu> * * Pauline Middelink : Made cmdline,envline only break at '\0's, to * make sure SET_PROCTITLE works. Also removed * bad '!' which forced address recalculation for * EVERY character on the current page. * <middelin@polyware.iaf.nl> * * Danny ter Haar : added cpuinfo * <dth@cistron.nl> * * Alessandro Rubini : profile extension. * <rubini@ipvvis.unipv.it> * * Jeff Tranter : added BogoMips field to cpuinfo * <Jeff_Tranter@Mitel.COM> * * Bruno Haible : remove 4K limit for the maps file * <haible@ma2s2.mathematik.uni-karlsruhe.de> * * Yves Arrouye : remove removal of trailing spaces in get_array. * <Yves.Arrouye@marin.fdn.fr> */#include <linux/types.h>#include <linux/errno.h>#include <linux/sched.h>#include <linux/kernel.h>#include <linux/kernel_stat.h>#include <linux/tty.h>#include <linux/user.h>#include <linux/a.out.h>#include <linux/string.h>#include <linux/mman.h>#include <linux/proc_fs.h>#include <linux/ioport.h>#include <linux/config.h>#include <linux/mm.h>#include <linux/pagemap.h>#include <linux/swap.h>#include <asm/segment.h>#include <asm/pgtable.h>#include <asm/io.h>#define LOAD_INT(x) ((x) >> FSHIFT)#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)#ifdef CONFIG_DEBUG_MALLOCint get_malloc(char * buffer);#endifstatic int read_core(struct inode * inode, struct file * file,char * buf, int count){ unsigned long p = file->f_pos, memsize; int read; int count1; char * pnt; struct user dump;#ifdef __i386__# define FIRST_MAPPED PAGE_SIZE /* we don't have page 0 mapped on x86.. */#else# define FIRST_MAPPED 0#endif memset(&dump, 0, sizeof(struct user)); dump.magic = CMAGIC; dump.u_dsize = MAP_NR(high_memory);#ifdef __alpha__ dump.start_data = PAGE_OFFSET;#endif if (count < 0) return -EINVAL; memsize = MAP_NR(high_memory + PAGE_SIZE) << PAGE_SHIFT; if (p >= memsize) return 0; if (count > memsize - p) count = memsize - p; read = 0; if (p < sizeof(struct user) && count > 0) { count1 = count; if (p + count1 > sizeof(struct user)) count1 = sizeof(struct user)-p; pnt = (char *) &dump + p; memcpy_tofs(buf,(void *) pnt, count1); buf += count1; p += count1; count -= count1; read += count1; } while (count > 0 && p < PAGE_SIZE + FIRST_MAPPED) { put_user(0,buf); buf++; p++; count--; read++; } memcpy_tofs(buf, (void *) (PAGE_OFFSET + p - PAGE_SIZE), count); read += count; file->f_pos += read; return read;}static struct file_operations proc_kcore_operations = { NULL, /* lseek */ read_core,};struct inode_operations proc_kcore_inode_operations = { &proc_kcore_operations, };/* * This function accesses profiling information. The returned data is * binary: the sampling step and the actual contents of the profile * buffer. Use of the program readprofile is recommended in order to * get meaningful info out of these data. */static int read_profile(struct inode *inode, struct file *file, char *buf, int count){ unsigned long p = file->f_pos; int read; char * pnt; unsigned int sample_step = 1 << prof_shift; if (count < 0) return -EINVAL; if (p >= (prof_len+1)*sizeof(unsigned int)) return 0; if (count > (prof_len+1)*sizeof(unsigned int) - p) count = (prof_len+1)*sizeof(unsigned int) - p; read = 0; while (p < sizeof(unsigned int) && count > 0) { put_user(*((char *)(&sample_step)+p),buf); buf++; p++; count--; read++; } pnt = (char *)prof_buffer + p - sizeof(unsigned int); memcpy_tofs(buf,(void *)pnt,count); read += count; file->f_pos += read; return read;}/* Writing to /proc/profile resets the counters */static int write_profile(struct inode * inode, struct file * file, const char * buf, int count){ int i=prof_len; while (i--) prof_buffer[i]=0UL; return count;}static struct file_operations proc_profile_operations = { NULL, /* lseek */ read_profile, write_profile,};struct inode_operations proc_profile_inode_operations = { &proc_profile_operations, };static int get_loadavg(char * buffer){ int a, b, c; a = avenrun[0] + (FIXED_1/200); b = avenrun[1] + (FIXED_1/200); c = avenrun[2] + (FIXED_1/200); return sprintf(buffer,"%d.%02d %d.%02d %d.%02d %d/%d %d\n", LOAD_INT(a), LOAD_FRAC(a), LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), nr_running, nr_tasks, last_pid);}static int get_kstat(char * buffer){ int i, len; unsigned sum = 0; extern unsigned long total_forks; for (i = 0 ; i < NR_IRQS ; i++) sum += kstat.interrupts[i]; len = sprintf(buffer, "cpu %u %u %u %lu\n" "disk %u %u %u %u\n" "disk_rio %u %u %u %u\n" "disk_wio %u %u %u %u\n" "disk_rblk %u %u %u %u\n" "disk_wblk %u %u %u %u\n" "page %u %u\n" "swap %u %u\n" "intr %u", kstat.cpu_user, kstat.cpu_nice, kstat.cpu_system, jiffies - (kstat.cpu_user + kstat.cpu_nice + kstat.cpu_system), kstat.dk_drive[0], kstat.dk_drive[1], kstat.dk_drive[2], kstat.dk_drive[3], kstat.dk_drive_rio[0], kstat.dk_drive_rio[1], kstat.dk_drive_rio[2], kstat.dk_drive_rio[3], kstat.dk_drive_wio[0], kstat.dk_drive_wio[1], kstat.dk_drive_wio[2], kstat.dk_drive_wio[3], kstat.dk_drive_rblk[0], kstat.dk_drive_rblk[1], kstat.dk_drive_rblk[2], kstat.dk_drive_rblk[3], kstat.dk_drive_wblk[0], kstat.dk_drive_wblk[1], kstat.dk_drive_wblk[2], kstat.dk_drive_wblk[3], kstat.pgpgin, kstat.pgpgout, kstat.pswpin, kstat.pswpout, sum); for (i = 0 ; i < NR_IRQS ; i++) len += sprintf(buffer + len, " %u", kstat.interrupts[i]); len += sprintf(buffer + len, "\nctxt %u\n" "btime %lu\n" "processes %lu\n", kstat.context_swtch, xtime.tv_sec - jiffies / HZ, total_forks); return len;}static int get_uptime(char * buffer){ unsigned long uptime; unsigned long idle; uptime = jiffies; idle = task[0]->utime + task[0]->stime; /* The formula for the fraction parts really is ((t * 100) / HZ) % 100, but that would overflow about every five days at HZ == 100. Therefore the identity a = (a / b) * b + a % b is used so that it is calculated as (((t / HZ) * 100) + ((t % HZ) * 100) / HZ) % 100. The part in front of the '+' always evaluates as 0 (mod 100). All divisions in the above formulas are truncating. For HZ being a power of 10, the calculations simplify to the version in the #else part (if the printf format is adapted to the same number of digits as zeroes in HZ. */#if HZ!=100 return sprintf(buffer,"%lu.%02lu %lu.%02lu\n", uptime / HZ, (((uptime % HZ) * 100) / HZ) % 100, idle / HZ, (((idle % HZ) * 100) / HZ) % 100);#else return sprintf(buffer,"%lu.%02lu %lu.%02lu\n", uptime / HZ, uptime % HZ, idle / HZ, idle % HZ);#endif}static int get_meminfo(char * buffer){ struct sysinfo i; int len; len = show_free_areas_proc(buffer); si_meminfo(&i); si_swapinfo(&i); len += sprintf(buffer + len, " total: used: free: shared: buffers: cached:\n" "Mem: %8lu %8lu %8lu %8lu %8lu %8lu\n" "Swap: %8lu %8lu %8lu\n", i.totalram, i.totalram-i.freeram, i.freeram, i.sharedram, i.bufferram, page_cache_size*PAGE_SIZE, i.totalswap, i.totalswap-i.freeswap, i.freeswap); /* * Tagged format, for easy grepping and expansion. The above will go away * eventually, once the tools have been updated. */ return len + sprintf(buffer+len, "MemTotal: %8lu kB\n" "MemFree: %8lu kB\n" "MemShared: %8lu kB\n" "Buffers: %8lu kB\n" "Cached: %8lu kB\n" "SwapTotal: %8lu kB\n" "SwapFree: %8lu kB\n", i.totalram >> 10, i.freeram >> 10, i.sharedram >> 10, i.bufferram >> 10, page_cache_size << (PAGE_SHIFT - 10), i.totalswap >> 10, i.freeswap >> 10);}static int get_version(char * buffer){ extern const char *linux_banner; strcpy(buffer, linux_banner); return strlen(buffer);}static int get_cmdline(char * buffer){ extern char saved_command_line[]; return sprintf(buffer, "%s\n", saved_command_line);}static struct task_struct ** get_task(pid_t pid){ struct task_struct ** p; p = task; while (++p < task+NR_TASKS) { if (*p && (*p)->pid == pid) return p; } return NULL;}static unsigned long get_phys_addr(struct task_struct * p, unsigned long ptr){#ifdef NO_MM return ptr;#else pgd_t *page_dir; pmd_t *page_middle; pte_t pte; if (!p || !p->mm || ptr >= TASK_SIZE) return 0; page_dir = pgd_offset(p->mm,ptr); if (pgd_none(*page_dir)) return 0; if (pgd_bad(*page_dir)) { printk("bad page directory entry %08lx\n", pgd_val(*page_dir)); pgd_clear(page_dir); return 0; } page_middle = pmd_offset(page_dir,ptr); if (pmd_none(*page_middle)) return 0; if (pmd_bad(*page_middle)) { printk("bad page middle entry %08lx\n", pmd_val(*page_middle)); pmd_clear(page_middle); return 0; } pte = *pte_offset(page_middle,ptr); if (!pte_present(pte)) return 0; return pte_page(pte) + (ptr & ~PAGE_MASK);#endif}static int get_array(struct task_struct ** p, unsigned long start, unsigned long end, char * buffer){ unsigned long addr; int size = 0, result = 0; char c; if (start >= end) return result; for (;;) { addr = get_phys_addr(*p, start); if (!addr) return result; do { c = *(char *) addr; if (!c) result = size; if (size < PAGE_SIZE) buffer[size++] = c; else return result; addr++; start++; if (!c && start >= end) return result; } while (addr & ~PAGE_MASK); } return result;}static int get_env(int pid, char * buffer){ struct task_struct ** p = get_task(pid); if (!p || !*p || !(*p)->mm) return 0; return get_array(p, (*p)->mm->env_start, (*p)->mm->env_end, buffer);}static int get_arg(int pid, char * buffer){ struct task_struct ** p = get_task(pid); if (!p || !*p || !(*p)->mm) return 0; return get_array(p, (*p)->mm->arg_start, (*p)->mm->arg_end, buffer);}static unsigned long get_wchan(struct task_struct *p){ if (!p || p == current || p->state == TASK_RUNNING) return 0;#if defined(__i386__) { unsigned long ebp, eip; unsigned long stack_page; int count = 0;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?