/proc/$pid/目录的内核源码实现

/proc/$pid/目录作为基础的proc文件系统操作,是在fs/proc中注册的。参见fs/proc/base.c。

具体的定义和相应实现可以参见struct pid_entry tgid_base_stuff[]和struct pid_entry tid_base_stuff[]两个数组,分别注册进程和线程的文件。

以/proc/$pid/stat为例,找到"stat"这一项,stat的数据就是通过proc_tgid_stat命令生成。

struct pid_entry {
	const char *name;
	unsigned int len;
	umode_t mode;
	const struct inode_operations *iop;
	const struct file_operations *fop;
	union proc_op op;
};

static const struct pid_entry tgid_base_stuff[] = {
	DIR("task",       S_IRUGO|S_IXUGO, proc_task_inode_operations, proc_task_operations),
	DIR("fd",         S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
	DIR("map_files",  S_IRUSR|S_IXUSR, proc_map_files_inode_operations, proc_map_files_operations),
	DIR("fdinfo",     S_IRUGO|S_IXUGO, proc_fdinfo_inode_operations, proc_fdinfo_operations),
	DIR("ns",	  S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
#ifdef CONFIG_NET
	DIR("net",        S_IRUGO|S_IXUGO, proc_net_inode_operations, proc_net_operations),
#endif
	REG("environ",    S_IRUSR, proc_environ_operations),
	REG("auxv",       S_IRUSR, proc_auxv_operations),
	ONE("status",     S_IRUGO, proc_pid_status),
	ONE("personality", S_IRUSR, proc_pid_personality),
	ONE("limits",	  S_IRUGO, proc_pid_limits),
#ifdef CONFIG_SCHED_DEBUG
	REG("sched",      S_IRUGO|S_IWUSR, proc_pid_sched_operations),
#endif
#ifdef CONFIG_SCHED_AUTOGROUP
	REG("autogroup",  S_IRUGO|S_IWUSR, proc_pid_sched_autogroup_operations),
#endif
#ifdef CONFIG_TIME_NS
	REG("timens_offsets",  S_IRUGO|S_IWUSR, proc_timens_offsets_operations),
#endif
	REG("comm",      S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
	ONE("syscall",    S_IRUSR, proc_pid_syscall),
#endif
	REG("cmdline",    S_IRUGO, proc_pid_cmdline_ops),
	ONE("stat",       S_IRUGO, proc_tgid_stat),
	ONE("statm",      S_IRUGO, proc_pid_statm),
	REG("maps",       S_IRUGO, proc_pid_maps_operations),
#ifdef CONFIG_NUMA
	REG("numa_maps",  S_IRUGO, proc_pid_numa_maps_operations),
#endif
	REG("mem",        S_IRUSR|S_IWUSR, proc_mem_operations),
	LNK("cwd",        proc_cwd_link),
	LNK("root",       proc_root_link),
	LNK("exe",        proc_exe_link),
	REG("mounts",     S_IRUGO, proc_mounts_operations),
	REG("mountinfo",  S_IRUGO, proc_mountinfo_operations),
	REG("mountstats", S_IRUSR, proc_mountstats_operations),
#ifdef CONFIG_PROC_PAGE_MONITOR
	REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
	REG("smaps",      S_IRUGO, proc_pid_smaps_operations),
	REG("smaps_rollup", S_IRUGO, proc_pid_smaps_rollup_operations),
	REG("pagemap",    S_IRUSR, proc_pagemap_operations),
#endif
#ifdef CONFIG_SECURITY
	DIR("attr",       S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
#endif
#ifdef CONFIG_KALLSYMS
	ONE("wchan",      S_IRUGO, proc_pid_wchan),
#endif
#ifdef CONFIG_STACKTRACE
	ONE("stack",      S_IRUSR, proc_pid_stack),
#endif
#ifdef CONFIG_SCHED_INFO
	ONE("schedstat",  S_IRUGO, proc_pid_schedstat),
#endif
#ifdef CONFIG_LATENCYTOP
	REG("latency",  S_IRUGO, proc_lstats_operations),
#endif
#ifdef CONFIG_PROC_PID_CPUSET
	ONE("cpuset",     S_IRUGO, proc_cpuset_show),
#endif
#ifdef CONFIG_CGROUPS
	ONE("cgroup",  S_IRUGO, proc_cgroup_show),
#endif
#ifdef CONFIG_PROC_CPU_RESCTRL
	ONE("cpu_resctrl_groups", S_IRUGO, proc_resctrl_show),
#endif
	ONE("oom_score",  S_IRUGO, proc_oom_score),
	REG("oom_adj",    S_IRUGO|S_IWUSR, proc_oom_adj_operations),
	REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
#ifdef CONFIG_AUDIT
	REG("loginuid",   S_IWUSR|S_IRUGO, proc_loginuid_operations),
	REG("sessionid",  S_IRUGO, proc_sessionid_operations),
#endif
#ifdef CONFIG_FAULT_INJECTION
	REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
	REG("fail-nth", 0644, proc_fail_nth_operations),
#endif
#ifdef CONFIG_ELF_CORE
	REG("coredump_filter", S_IRUGO|S_IWUSR, proc_coredump_filter_operations),
#endif
#ifdef CONFIG_TASK_IO_ACCOUNTING
	ONE("io",	S_IRUSR, proc_tgid_io_accounting),
#endif
#ifdef CONFIG_USER_NS
	REG("uid_map",    S_IRUGO|S_IWUSR, proc_uid_map_operations),
	REG("gid_map",    S_IRUGO|S_IWUSR, proc_gid_map_operations),
	REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
	REG("setgroups",  S_IRUGO|S_IWUSR, proc_setgroups_operations),
#endif
#if defined(CONFIG_CHECKPOINT_RESTORE) && defined(CONFIG_POSIX_TIMERS)
	REG("timers",	  S_IRUGO, proc_timers_operations),
#endif
	REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations),
#ifdef CONFIG_LIVEPATCH
	ONE("patch_state",  S_IRUSR, proc_pid_patch_state),
#endif
#ifdef CONFIG_STACKLEAK_METRICS
	ONE("stack_depth", S_IRUGO, proc_stack_depth),
#endif
#ifdef CONFIG_PROC_PID_ARCH_STATUS
	ONE("arch_status", S_IRUGO, proc_pid_arch_status),
#endif
#ifdef CONFIG_SECCOMP_CACHE_DEBUG
	ONE("seccomp_cache", S_IRUSR, proc_pid_seccomp_cache),
#endif
};

proc_tgid_stat又调用了do_task_stat接口,这个接口里可以与我们实际cat /proc/$pid/stat的结果相对应。

# cat /proc/9592/stat
9592 (sdpcie) S 9589 9548 9548 0 -1 138412160 524733 65951 317 4 2980 613 11 22 20 0 92 0 2799 10020995072 201379 18446744073709551615 4313088 17342146 140725323315232 0 0 0 268444224 4100 17987 0 0 0 17 0 0 0 10 0 0 26697280 29338624 93556736 140725323320973 140725323321150 140725323321150 140725323321316 0

其中第24个参数是物理内存占用,RSS值。查看RSS的计算方式是通过一个get_mm_rss(mm)的接口获得:

//结果输出
seq_put_decimal_ull(m, " ", mm ? get_mm_rss(mm) : 0);

get_mm_rss(mm)的实现接口如下。所以是mm_struct中有一个专门的rss_stat结构体用来记录RSS内存占用情况。

static inline unsigned long get_mm_rss(struct mm_struct *mm)
{
	return get_mm_counter(mm, MM_FILEPAGES) +
		get_mm_counter(mm, MM_ANONPAGES) +
		get_mm_counter(mm, MM_SHMEMPAGES);
}
static inline unsigned long get_mm_counter(struct mm_struct *mm, int member)
{
	long val = atomic_long_read(&mm->rss_stat.count[member]);

#ifdef SPLIT_RSS_COUNTING
	/*
	 * counter is updated in asynchronous manner and may go to minus.
	 * But it's never be expected number for users.
	 */
	if (val < 0)
		val = 0;
#endif
	return (unsigned long)val;
}

rss_stat结构体的定义如下。一共有4组值,分别表示 文件页(文件映射,代码段也在这里?),匿名映射页(堆/栈)、匿名换出页面、共享内存页面。

而我们的/proc/$pid/stat里的RSS,没有包括换出的页面,所以是当前实际占用的物理内存。现在的服务器一般不会设置虚拟内存和页面换出了。

/*
 * When updating this, please also update struct resident_page_types[] in
 * kernel/fork.c
 */
enum {
	MM_FILEPAGES,	/* Resident file mapping pages */
	MM_ANONPAGES,	/* Resident anonymous pages */
	MM_SWAPENTS,	/* Anonymous swap entries */
	MM_SHMEMPAGES,	/* Resident shared memory pages */
	NR_MM_COUNTERS
};

struct mm_rss_stat {
	atomic_long_t count[NR_MM_COUNTERS];
};

当然也有详细的官方手册可以查阅/proc下面的参数。

d​​​​​​​proc(5) - Linux manual page

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
/proc/$pid/maps 文件包含了一个进程的内存映射信息,每一行表示一个内存区域映射。每行的字段含义如下: 1. 起始地址:内存区域的起始地址。 2. 结束地址:内存区域的结束地址。 3. 权限:内存区域的权限,包括读(R)、写(W)、执行(X)、私有权限(P)和共享权限(S)。 4. 偏移量:内存区域相对于文件开头的偏移量,如果不是从文件映射过来,则为0。 5. 设备号:内存区域所在的设备号。 6. 节点号:内存区域所在的节点号。 7. 文件名:对应的文件名,如果是匿名映射,则为[ anon ]。 例如,下面是一个/proc/$pid/maps文件的示例: ``` 00400000-0040b000 r-xp 00000000 00:14 54790 /bin/cat 0060a000-0060b000 r--p 0000a000 00:14 54790 /bin/cat 0060b000-0060c000 rw-p 0000b000 00:14 54790 /bin/cat 00e2a000-00e4b000 rw-p 00000000 00:00 0 [heap] 7f3c5c000000-7f3c5c021000 rw-p 00000000 00:00 0 7f3c5c021000-7f3c60000000 ---p 00000000 00:00 0 7f3c615e4000-7f3c615e5000 rw-p 00000000 00:00 0 7f3c615e5000-7f3c615f2000 r-xp 00000000 08:01 18381 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so 7f3c615f2000-7f3c617f1000 ---p 0000d000 08:01 18381 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so 7f3c617f1000-7f3c617f2000 r--p 0000c000 08:01 18381 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so 7f3c617f2000-7f3c617f3000 rw-p 0000d000 08:01 18381 /usr/lib/x86_64-linux-gnu/libnss_files-2.31.so ... ``` 这个示例中,第一行表示了/bin/cat这个可执行文件的代码段,第二行表示了它的只读数据段,第三行表示了它的读写数据段,第四行表示了进程的堆空间,第五行表示了一个匿名映射,第六行到第十行表示了一个共享库的内存映射。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值