📄 array.c
字号:
while (address < end) {
statm_pmd_range(pgd, address, end - address, pages, shared, dirty, total);
address = (address + PGDIR_SIZE) & PGDIR_MASK;
pgd++;
}
}
static int get_statm(int pid, char * buffer)
{
struct task_struct ** p = get_task(pid), *tsk;
int size=0, resident=0, share=0, trs=0, lrs=0, drs=0, dt=0;
if (!p || (tsk = *p) == NULL)
return 0;
if (tsk->mm && tsk->mm != &init_mm) {
struct vm_area_struct * vma = tsk->mm->mmap;
while (vma) {
pgd_t *pgd = pgd_offset(tsk->mm, vma->vm_start);
int pages = 0, shared = 0, dirty = 0, total = 0;
statm_pgd_range(pgd, vma->vm_start, vma->vm_end, &pages, &shared, &dirty, &total);
resident += pages;
share += shared;
dt += dirty;
size += total;
if (vma->vm_flags & VM_EXECUTABLE)
trs += pages; /* text */
else if (vma->vm_flags & VM_GROWSDOWN)
drs += pages; /* stack */
else if (vma->vm_end > 0x60000000)
lrs += pages; /* library */
else
drs += pages;
vma = vma->vm_next;
}
}
return sprintf(buffer,"%d %d %d %d %d %d %d\n",
size, resident, share, trs, lrs, drs, dt);
}
/*
* The way we support synthetic files > 4K
* - without storing their contents in some buffer and
* - without walking through the entire synthetic file until we reach the
* position of the requested data
* is to cleverly encode the current position in the file's f_pos field.
* There is no requirement that a read() call which returns `count' bytes
* of data increases f_pos by exactly `count'.
*
* This idea is Linus' one. Bruno implemented it.
*/
/*
* For the /proc/<pid>/maps file, we use fixed length records, each containing
* a single line.
*/
#define MAPS_LINE_LENGTH 1024
#define MAPS_LINE_SHIFT 10
/*
* f_pos = (number of the vma in the task->mm->mmap list) * MAPS_LINE_LENGTH
* + (index into the line)
*/
/* for systems with sizeof(void*) == 4: */
#define MAPS_LINE_FORMAT4 "%08lx-%08lx %s %08lx %s %lu\n"
#define MAPS_LINE_MAX4 49 /* sum of 8 1 8 1 4 1 8 1 5 1 10 1 */
/* for systems with sizeof(void*) == 8: */
#define MAPS_LINE_FORMAT8 "%016lx-%016lx %s %016lx %s %lu\n"
#define MAPS_LINE_MAX8 73 /* sum of 16 1 16 1 4 1 16 1 5 1 10 1 */
#define MAPS_LINE_MAX MAPS_LINE_MAX8
static int read_maps (int pid, struct file * file, char * buf, int count)
{
struct task_struct ** p = get_task(pid);
char * destptr;
loff_t lineno;
int column;
struct vm_area_struct * map;
int i;
if (!p || !*p)
return -EINVAL;
if (!(*p)->mm || (*p)->mm == &init_mm || count == 0)
return 0;
/* decode f_pos */
lineno = file->f_pos >> MAPS_LINE_SHIFT;
column = file->f_pos & (MAPS_LINE_LENGTH-1);
/* quickly go to line lineno */
for (map = (*p)->mm->mmap, i = 0; map && (i < lineno); map = map->vm_next, i++)
continue;
destptr = buf;
for ( ; map ; ) {
/* produce the next line */
char line[MAPS_LINE_MAX+1];
char str[5], *cp = str;
int flags;
kdev_t dev;
unsigned long ino;
int len;
flags = map->vm_flags;
*cp++ = flags & VM_READ ? 'r' : '-';
*cp++ = flags & VM_WRITE ? 'w' : '-';
*cp++ = flags & VM_EXEC ? 'x' : '-';
*cp++ = flags & VM_MAYSHARE ? 's' : 'p';
*cp++ = 0;
if (map->vm_inode != NULL) {
dev = map->vm_inode->i_dev;
ino = map->vm_inode->i_ino;
} else {
dev = 0;
ino = 0;
}
len = sprintf(line,
sizeof(void*) == 4 ? MAPS_LINE_FORMAT4 : MAPS_LINE_FORMAT8,
map->vm_start, map->vm_end, str, map->vm_offset,
kdevname(dev), ino);
if (column >= len) {
column = 0; /* continue with next line at column 0 */
lineno++;
map = map->vm_next;
continue;
}
i = len-column;
if (i > count)
i = count;
memcpy_tofs(destptr, line+column, i);
destptr += i; count -= i;
column += i;
if (column >= len) {
column = 0; /* next time: next line at column 0 */
lineno++;
map = map->vm_next;
}
/* done? */
if (count == 0)
break;
/* By writing to user space, we might have slept.
* Stop the loop, to avoid a race condition.
*/
if (*p != current)
break;
}
/* encode f_pos */
file->f_pos = (lineno << MAPS_LINE_SHIFT) + column;
return destptr-buf;
}
#endif /* !NO_MM */
#ifdef CONFIG_MODULES
extern int get_module_list(char *);
extern int get_ksyms_list(char *, char **, off_t, int);
#endif
extern int get_device_list(char *);
extern int get_filesystem_list(char *);
extern int get_filesystem_info( char * );
extern int get_irq_list(char *);
extern int get_serialinfo(char *);
extern int get_dma_list(char *);
extern int get_cpuinfo(char *);
extern int get_pci_list(char*);
extern int get_md_status (char *);
extern int get_rtc_status (char *);
extern int get_locks_status (char *, char **, off_t, int);
#ifdef __SMP_PROF__
extern int get_smp_prof_list(char *);
#endif
static int get_root_array(char * page, int type, char **start, off_t offset, int length)
{
switch (type) {
case PROC_LOADAVG:
return get_loadavg(page);
case PROC_UPTIME:
return get_uptime(page);
case PROC_MEMINFO:
return get_meminfo(page);
#ifdef CONFIG_PCI
case PROC_PCI:
return get_pci_list(page);
#endif
case PROC_CPUINFO:
return get_cpuinfo(page);
case PROC_VERSION:
return get_version(page);
#ifdef CONFIG_DEBUG_MALLOC
case PROC_MALLOC:
return get_malloc(page);
#endif
#ifdef CONFIG_MODULES
case PROC_MODULES:
return get_module_list(page);
case PROC_KSYMS:
return get_ksyms_list(page, start, offset, length);
#endif
case PROC_STAT:
return get_kstat(page);
case PROC_DEVICES:
return get_device_list(page);
case PROC_INTERRUPTS:
return get_irq_list(page);
case PROC_SERIAL:
return get_serialinfo(page);
case PROC_FILESYSTEMS:
return get_filesystem_list(page);
case PROC_DMA:
return get_dma_list(page);
case PROC_IOPORTS:
return get_ioport_list(page);
#ifdef CONFIG_BLK_DEV_MD
case PROC_MD:
return get_md_status(page);
#endif
#ifdef __SMP_PROF__
case PROC_SMP_PROF:
return get_smp_prof_list(page);
#endif
case PROC_CMDLINE:
return get_cmdline(page);
case PROC_MTAB:
return get_filesystem_info( page );
#ifdef CONFIG_RTC
case PROC_RTC:
return get_rtc_status(page);
#endif
case PROC_LOCKS:
return get_locks_status(page, start, offset, length);
}
return -EBADF;
}
static int get_process_array(char * page, int pid, int type)
{
switch (type) {
case PROC_PID_STATUS:
return get_status(pid, page);
case PROC_PID_ENVIRON:
return get_env(pid, page);
case PROC_PID_CMDLINE:
return get_arg(pid, page);
case PROC_PID_STAT:
return get_stat(pid, page);
#ifndef NO_MM
case PROC_PID_STATM:
return get_statm(pid, page);
#endif /* !NO_MM */
}
return -EBADF;
}
static inline int fill_array(char * page, int pid, int type, char **start, off_t offset, int length)
{
if (pid)
return get_process_array(page, pid, type);
return get_root_array(page, type, start, offset, length);
}
#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */
static int array_read(struct inode * inode, struct file * file,char * buf, int count)
{
unsigned long page;
char *start;
int length;
int end;
unsigned int type, pid;
struct proc_dir_entry *dp;
if (count < 0)
return -EINVAL;
if (count > PROC_BLOCK_SIZE)
count = PROC_BLOCK_SIZE;
if (!(page = __get_free_page(GFP_KERNEL)))
return -ENOMEM;
type = inode->i_ino;
pid = type >> 16;
type &= 0x0000ffff;
start = NULL;
dp = (struct proc_dir_entry *) inode->u.generic_ip;
if (dp->get_info)
length = dp->get_info((char *)page, &start, file->f_pos,
count, 0);
else
length = fill_array((char *) page, pid, type,
&start, file->f_pos, count);
if (length < 0) {
free_page(page);
return length;
}
if (start != NULL) {
/* We have had block-adjusting processing! */
memcpy_tofs(buf, start, length);
file->f_pos += length;
count = length;
} else {
/* Static 4kB (or whatever) block capacity */
if (file->f_pos >= length) {
free_page(page);
return 0;
}
if (count + file->f_pos > length)
count = length - file->f_pos;
end = count + file->f_pos;
memcpy_tofs(buf, (char *) page + file->f_pos, count);
file->f_pos = end;
}
free_page(page);
return count;
}
static struct file_operations proc_array_operations = {
NULL, /* array_lseek */
array_read,
NULL, /* array_write */
NULL, /* array_readdir */
NULL, /* array_select */
NULL, /* array_ioctl */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* can't fsync */
};
struct inode_operations proc_array_inode_operations = {
&proc_array_operations, /* default base directory file-ops */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
NULL /* permission */
};
static int arraylong_read (struct inode * inode, struct file * file, char * buf, int count)
{
#ifndef NO_MM
unsigned int pid = inode->i_ino >> 16;
unsigned int type = inode->i_ino & 0x0000ffff;
if (count < 0)
return -EINVAL;
switch (type) {
case PROC_PID_MAPS:
return read_maps(pid, file, buf, count);
}
#endif /* !NO_MM */
return -EINVAL;
}
static struct file_operations proc_arraylong_operations = {
NULL, /* array_lseek */
arraylong_read,
NULL, /* array_write */
NULL, /* array_readdir */
NULL, /* array_select */
NULL, /* array_ioctl */
NULL, /* mmap */
NULL, /* no special open code */
NULL, /* no special release code */
NULL /* can't fsync */
};
struct inode_operations proc_arraylong_inode_operations = {
&proc_arraylong_operations, /* default base directory file-ops */
NULL, /* create */
NULL, /* lookup */
NULL, /* link */
NULL, /* unlink */
NULL, /* symlink */
NULL, /* mkdir */
NULL, /* rmdir */
NULL, /* mknod */
NULL, /* rename */
NULL, /* readlink */
NULL, /* follow_link */
NULL, /* readpage */
NULL, /* writepage */
NULL, /* bmap */
NULL, /* truncate */
NULL /* permission */
};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -