📄 proc_misc.c
字号:
/* * linux/fs/proc/proc_misc.c * * linux/fs/proc/array.c * Copyright (C) 1992 by Linus Torvalds * based on ideas by Darren Senn * * This used to be the part of array.c. See the rest of history and credits * there. I took this into a separate file and switched the thing to generic * proc_file_inode_operations, leaving in array.c only per-process stuff. * Inumbers allocation made dynamic (via create_proc_entry()). AV, May 1999. * * Changes: * Fulton Green : Encapsulated position metric calculations. * <kernel@FultonGreen.com> */#include <linux/types.h>#include <linux/errno.h>#include <linux/time.h>#include <linux/kernel.h>#include <linux/kernel_stat.h>#include <linux/fs.h>#include <linux/tty.h>#include <linux/string.h>#include <linux/mman.h>#include <linux/proc_fs.h>#include <linux/ioport.h>#include <linux/mm.h>#include <linux/mmzone.h>#include <linux/pagemap.h>#include <linux/swap.h>#include <linux/slab.h>#include <linux/smp.h>#include <linux/signal.h>#include <linux/module.h>#include <linux/init.h>#include <linux/seq_file.h>#include <linux/times.h>#include <linux/profile.h>#include <linux/utsname.h>#include <linux/blkdev.h>#include <linux/hugetlb.h>#include <linux/jiffies.h>#include <linux/sysrq.h>#include <linux/vmalloc.h>#include <linux/crash_dump.h>#include <linux/pid_namespace.h>#include <asm/uaccess.h>#include <asm/pgtable.h>#include <asm/io.h>#include <asm/tlb.h>#include <asm/div64.h>#include "internal.h"#define LOAD_INT(x) ((x) >> FSHIFT)#define LOAD_FRAC(x) LOAD_INT(((x) & (FIXED_1-1)) * 100)/* * Warning: stuff below (imported functions) assumes that its output will fit * into one page. For some of those functions it may be wrong. Moreover, we * have a way to deal with that gracefully. Right now I used straightforward * wrappers, but this needs further analysis wrt potential overflows. */extern int get_hardware_list(char *);extern int get_stram_list(char *);extern int get_filesystem_list(char *);extern int get_exec_domain_list(char *);extern int get_dma_list(char *);static int proc_calc_metrics(char *page, char **start, off_t off, int count, int *eof, int len){ if (len <= off+count) *eof = 1; *start = page + off; len -= off; if (len>count) len = count; if (len<0) len = 0; return len;}static int loadavg_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ int a, b, c; int len; a = avenrun[0] + (FIXED_1/200); b = avenrun[1] + (FIXED_1/200); c = avenrun[2] + (FIXED_1/200); len = sprintf(page,"%d.%02d %d.%02d %d.%02d %ld/%d %d\n", LOAD_INT(a), LOAD_FRAC(a), LOAD_INT(b), LOAD_FRAC(b), LOAD_INT(c), LOAD_FRAC(c), nr_running(), nr_threads, task_active_pid_ns(current)->last_pid); return proc_calc_metrics(page, start, off, count, eof, len);}static int uptime_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ struct timespec uptime; struct timespec idle; int len; cputime_t idletime = cputime_add(init_task.utime, init_task.stime); do_posix_clock_monotonic_gettime(&uptime); monotonic_to_bootbased(&uptime); cputime_to_timespec(idletime, &idle); len = sprintf(page,"%lu.%02lu %lu.%02lu\n", (unsigned long) uptime.tv_sec, (uptime.tv_nsec / (NSEC_PER_SEC / 100)), (unsigned long) idle.tv_sec, (idle.tv_nsec / (NSEC_PER_SEC / 100))); return proc_calc_metrics(page, start, off, count, eof, len);}static int meminfo_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ struct sysinfo i; int len; unsigned long committed; unsigned long allowed; struct vmalloc_info vmi; long cached;/* * display in kilobytes. */#define K(x) ((x) << (PAGE_SHIFT - 10)) si_meminfo(&i); si_swapinfo(&i); committed = atomic_read(&vm_committed_space); allowed = ((totalram_pages - hugetlb_total_pages()) * sysctl_overcommit_ratio / 100) + total_swap_pages; cached = global_page_state(NR_FILE_PAGES) - total_swapcache_pages - i.bufferram; if (cached < 0) cached = 0; get_vmalloc_info(&vmi); /* * Tagged format, for easy grepping and expansion. */ len = sprintf(page, "MemTotal: %8lu kB\n" "MemFree: %8lu kB\n" "Buffers: %8lu kB\n" "Cached: %8lu kB\n" "SwapCached: %8lu kB\n" "Active: %8lu kB\n" "Inactive: %8lu kB\n"#ifdef CONFIG_HIGHMEM "HighTotal: %8lu kB\n" "HighFree: %8lu kB\n" "LowTotal: %8lu kB\n" "LowFree: %8lu kB\n"#endif "SwapTotal: %8lu kB\n" "SwapFree: %8lu kB\n" "Dirty: %8lu kB\n" "Writeback: %8lu kB\n" "AnonPages: %8lu kB\n" "Mapped: %8lu kB\n" "Slab: %8lu kB\n" "SReclaimable: %8lu kB\n" "SUnreclaim: %8lu kB\n" "PageTables: %8lu kB\n" "NFS_Unstable: %8lu kB\n" "Bounce: %8lu kB\n" "CommitLimit: %8lu kB\n" "Committed_AS: %8lu kB\n" "VmallocTotal: %8lu kB\n" "VmallocUsed: %8lu kB\n" "VmallocChunk: %8lu kB\n", K(i.totalram), K(i.freeram), K(i.bufferram), K(cached), K(total_swapcache_pages), K(global_page_state(NR_ACTIVE)), K(global_page_state(NR_INACTIVE)),#ifdef CONFIG_HIGHMEM K(i.totalhigh), K(i.freehigh), K(i.totalram-i.totalhigh), K(i.freeram-i.freehigh),#endif K(i.totalswap), K(i.freeswap), K(global_page_state(NR_FILE_DIRTY)), K(global_page_state(NR_WRITEBACK)), K(global_page_state(NR_ANON_PAGES)), K(global_page_state(NR_FILE_MAPPED)), K(global_page_state(NR_SLAB_RECLAIMABLE) + global_page_state(NR_SLAB_UNRECLAIMABLE)), K(global_page_state(NR_SLAB_RECLAIMABLE)), K(global_page_state(NR_SLAB_UNRECLAIMABLE)), K(global_page_state(NR_PAGETABLE)), K(global_page_state(NR_UNSTABLE_NFS)), K(global_page_state(NR_BOUNCE)), K(allowed), K(committed), (unsigned long)VMALLOC_TOTAL >> 10, vmi.used >> 10, vmi.largest_chunk >> 10 ); len += hugetlb_report_meminfo(page + len); return proc_calc_metrics(page, start, off, count, eof, len);#undef K}extern struct seq_operations fragmentation_op;static int fragmentation_open(struct inode *inode, struct file *file){ (void)inode; return seq_open(file, &fragmentation_op);}static const struct file_operations fragmentation_file_operations = { .open = fragmentation_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};extern struct seq_operations pagetypeinfo_op;static int pagetypeinfo_open(struct inode *inode, struct file *file){ return seq_open(file, &pagetypeinfo_op);}static const struct file_operations pagetypeinfo_file_ops = { .open = pagetypeinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};extern struct seq_operations zoneinfo_op;static int zoneinfo_open(struct inode *inode, struct file *file){ return seq_open(file, &zoneinfo_op);}static const struct file_operations proc_zoneinfo_file_operations = { .open = zoneinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};static int version_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ int len; len = snprintf(page, PAGE_SIZE, linux_proc_banner, utsname()->sysname, utsname()->release, utsname()->version); return proc_calc_metrics(page, start, off, count, eof, len);}extern struct seq_operations cpuinfo_op;static int cpuinfo_open(struct inode *inode, struct file *file){ return seq_open(file, &cpuinfo_op);}static const struct file_operations proc_cpuinfo_operations = { .open = cpuinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};static int devinfo_show(struct seq_file *f, void *v){ int i = *(loff_t *) v; if (i < CHRDEV_MAJOR_HASH_SIZE) { if (i == 0) seq_printf(f, "Character devices:\n"); chrdev_show(f, i); }#ifdef CONFIG_BLOCK else { i -= CHRDEV_MAJOR_HASH_SIZE; if (i == 0) seq_printf(f, "\nBlock devices:\n"); blkdev_show(f, i); }#endif return 0;}static void *devinfo_start(struct seq_file *f, loff_t *pos){ if (*pos < (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE)) return pos; return NULL;}static void *devinfo_next(struct seq_file *f, void *v, loff_t *pos){ (*pos)++; if (*pos >= (BLKDEV_MAJOR_HASH_SIZE + CHRDEV_MAJOR_HASH_SIZE)) return NULL; return pos;}static void devinfo_stop(struct seq_file *f, void *v){ /* Nothing to do */}static struct seq_operations devinfo_ops = { .start = devinfo_start, .next = devinfo_next, .stop = devinfo_stop, .show = devinfo_show};static int devinfo_open(struct inode *inode, struct file *filp){ return seq_open(filp, &devinfo_ops);}static const struct file_operations proc_devinfo_operations = { .open = devinfo_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};extern struct seq_operations vmstat_op;static int vmstat_open(struct inode *inode, struct file *file){ return seq_open(file, &vmstat_op);}static const struct file_operations proc_vmstat_file_operations = { .open = vmstat_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};#ifdef CONFIG_PROC_HARDWAREstatic int hardware_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ int len = get_hardware_list(page); return proc_calc_metrics(page, start, off, count, eof, len);}#endif#ifdef CONFIG_STRAM_PROCstatic int stram_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data){ int len = get_stram_list(page); return proc_calc_metrics(page, start, off, count, eof, len);}#endif#ifdef CONFIG_BLOCKextern struct seq_operations partitions_op;static int partitions_open(struct inode *inode, struct file *file){ return seq_open(file, &partitions_op);}static const struct file_operations proc_partitions_operations = { .open = partitions_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release,};extern struct seq_operations diskstats_op;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -