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 + -
显示快捷键?