以进程1为例,查看proc长什么样子?
-
127|shell@tiny4412:/proc/1 # ls -l
-
dr-xr-xr-x root root 2014-01-01 12:07 attr
-
-r-------- root root 0 2014-01-01 12:07 auxv
-
-r--r--r-- root root 0 2014-01-01 12:07 cgroup
-
--w------- root root 0 2014-01-01 12:07 clear_refs
-
-r--r--r-- root root 0 2014-01-01 12:00 cmdline
-
-rw-r--r-- root root 0 2014-01-01 12:07 comm
-
-rw-r--r-- root root 0 2014-01-01 12:07 coredump_filter
-
lrwxrwxrwx root root 2014-01-01 12:07 cwd -> /
-
-r-------- root root 0 2014-01-01 12:07 environ
-
lrwxrwxrwx root root 2014-01-01 12:07 exe -> /init
-
dr-x------ root root 2014-01-01 12:07 fd
-
dr-x------ root root 2014-01-01 12:07 fdinfo
-
-r--r--r-- root root 0 2014-01-01 12:07 limits
-
-rw-r--r-- root root 0 2014-01-01 12:07 loginuid
-
-r--r--r-- root root 0 2014-01-01 12:07 maps ----------->比较关心映射关系是如何生成的
-
-rw------- root root 0 2014-01-01 12:07 mem
-
-r--r--r-- root root 0 2014-01-01 12:07 mountinfo
-
-r--r--r-- root root 0 2014-01-01 12:07 mounts
-
-r-------- root root 0 2014-01-01 12:07 mountstats
-
dr-xr-xr-x root root 2014-01-01 12:00 net
-
dr-x--x--x root root 2014-01-01 12:07 ns
-
-rw-r--r-- root root 0 2014-01-01 12:07 oom_adj
-
-r--r--r-- root root 0 2014-01-01 12:07 oom_killed
-
-r--r--r-- root root 0 2014-01-01 12:07 oom_score
-
-rw-r--r-- root root 0 2014-01-01 12:00 oom_score_adj
-
-r--r--r-- root root 0 2014-01-01 12:07 pagemap
-
-r--r--r-- root root 0 2014-01-01 12:07 personality
-
lrwxrwxrwx root root 2014-01-01 12:07 root -> /
-
-rw-r--r-- root root 0 2014-01-01 12:07 sched
-
-r--r--r-- root root 0 2014-01-01 12:07 schedstat
-
-r--r--r-- root root 0 2014-01-01 12:07 sessionid
-
-r--r--r-- root root 0 2014-01-01 12:00 smaps
-
-r--r--r-- root root 0 2014-01-01 12:07 stack
-
-r--r--r-- root root 0 2014-01-01 12:00 stat
-
-r--r--r-- root root 0 2014-01-01 12:07 statm
-
-r--r--r-- root root 0 2014-01-01 12:07 status
-
dr-xr-xr-x root root 2014-01-01 12:00 task
-
-r--r--r-- root root 0 2014-01-01 12:07 wchan
查看详细映射关系:
-
shell@tiny4412:/proc/1 # cat maps
-
00008000-00049000 r-xp 00000000 00:01 1422 /init
-
0004a000-0004c000 r--p 00041000 00:01 1422 /init
-
0004c000-0004f000 rw-p 00043000 00:01 1422 /init
-
0004f000-00052000 rw-p 00000000 00:00 0 [heap]
-
40017000-40019000 rw-p 00000000 00:00 0
-
40072000-40073000 r--p 00000000 00:00 0
-
40090000-400b0000 rw-s 00000000 00:0c 2056 /dev/__properties__
-
400b2000-400b3000 rw-p 00000000 00:00 0
-
40100000-40301000 rw-p 00000000 00:00 0
-
becd2000-becf3000 rw-p 00000000 00:00 0 [stack]
-
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
-
-
根据源码的解析:
-
vm_area_struct
-
unsigned long vm_start; /* Our start address within vm_mm. */
-
unsigned long vm_end; /* The first byte after our end address
-
within vm_mm. */
-
unsigned long vm_flags; /* Flags, see mm.h. */ 分别是读,写,共享/私有
-
/* Information about our backing store: */
-
unsigned long vm_pgoff; /* Offset (within vm_file) in PAGE_SIZE 页偏移
-
units, *not* PAGE_CACHE_SIZE */
-
-
vma->vm_file->f_path.dentry->d_inode-->i_sb->s_dev; 主设备号,次设备号
-
vma->vm_file->f_path.dentry->d_inode-->i_ino inode 号
-
最后就是 /*
-
* Print the dentry name for named mappings, and a
-
* special [heap] marker for the heap:
-
*/调用文件路径
-
linux源码位置及主要宏
android/linux-3.0.86/fs/proc/base.c
-
static const struct pid_entry tid_base_stuff[] = {
-
DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
-
DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
-
DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
-
REG("environ", S_IRUSR, proc_environ_operations),
-
INF("auxv", S_IRUSR, proc_pid_auxv),
-
ONE("status", S_IRUGO, proc_pid_status),
-
ONE("personality", S_IRUGO, proc_pid_personality),
-
INF("limits", S_IRUGO, proc_pid_limits),
-
#ifdef CONFIG_SCHED_DEBUG
-
REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
-
#endif
-
REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
-
#ifdef CONFIG_HAVE_ARCH_TRACEHOOK
-
INF("syscall", S_IRUGO, proc_pid_syscall),
-
#endif
-
INF("cmdline", S_IRUGO, proc_pid_cmdline),
-
ONE("stat", S_IRUGO, proc_tid_stat),
-
ONE("statm", S_IRUGO, proc_pid_statm),
-
REG("maps", S_IRUGO, proc_maps_operations), -------------------->关注映射
-
#ifdef CONFIG_NUMA
-
REG("numa_maps", S_IRUGO, proc_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),
-
#ifdef CONFIG_PROC_PAGE_MONITOR
-
REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
-
REG("smaps", S_IRUGO, proc_smaps_operations),
-
REG("pagemap", S_IRUGO, 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
-
INF("wchan", S_IRUGO, proc_pid_wchan),
-
#endif
-
#ifdef CONFIG_STACKTRACE
-
ONE("stack", S_IRUGO, proc_pid_stack),
-
#endif
-
#ifdef CONFIG_SCHEDSTATS
-
INF("schedstat", S_IRUGO, proc_pid_schedstat),
-
#endif
-
#ifdef CONFIG_LATENCYTOP
-
REG("latency", S_IRUGO, proc_lstats_operations),
-
#endif
-
#ifdef CONFIG_PROC_PID_CPUSET
-
REG("cpuset", S_IRUGO, proc_cpuset_operations),
-
#endif
-
#ifdef CONFIG_CGROUPS
-
REG("cgroup", S_IRUGO, proc_cgroup_operations),
-
#endif
-
INF("oom_score", S_IRUGO, proc_oom_score),
-
REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations),
-
REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
-
#ifdef CONFIG_ANDROID
-
REG("oom_killed", S_IRUGO, proc_oom_killed_operations),
-
#endif
-
#ifdef CONFIG_AUDITSYSCALL
-
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),
-
#endif
-
#ifdef CONFIG_TASK_IO_ACCOUNTING
-
INF("io", S_IRUSR, proc_tid_io_accounting),
-
#endif
-
#ifdef CONFIG_HARDWALL
-
INF("hardwall", S_IRUGO, proc_pid_hardwall),
-
#endif
-
};
pid_entry 是一个什么样的结构体?
struct pid_entry {
char *name; -------->这个应该就是proc目录下面对应文件名或者文件夹名称
int len;
mode_t mode; --------->权限
const struct inode_operations *iop; --------------->与inode 对应,我们在操作文件的时候,先找到文件名,然后通过文件名及路径找到inode,再通过inode找到它的操作方法
const struct file_operations *fop;
union proc_op op;
};
#define NOD(NAME, MODE, IOP, FOP, OP) {
.name = (NAME),
.len = sizeof(NAME) - 1,
.mode = MODE,
.iop = IOP,
.fop = FOP,
.op = OP,
}
#define DIR(NAME, MODE, iops, fops)
NOD(NAME, (S_IFDIR|(MODE)), &iops, &fops, {} ) ----------->对应目录信息的填充宏
例子: DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations)
dr-x------ root root 2014-01-01 12:07 fd
#define LNK(NAME, get_link)
NOD(NAME, (S_IFLNK|S_IRWXUGO),
&proc_pid_link_inode_operations, NULL, ----->链接文件
{ .proc_get_link = get_link } ) ------------------------>设置的是链接信息
例子: LNK("cwd", proc_cwd_link),
LNK("root", proc_root_link),
LNK("exe", proc_exe_link),
lrwxrwxrwx root root 2014-01-01 12:07 cwd -> / ----->当前工作目录
#define REG(NAME, MODE, fops)
NOD(NAME, (S_IFREG|(MODE)), NULL, &fops, {})--------->普通文件,只包含file_operation,因为仅仅是一个文件
REG("maps", S_IRUGO, proc_maps_operations),
const struct file_operations proc_maps_operations = {
.open = maps_open,
.read = seq_read, ------------------>和序列文件有关系
.llseek = seq_lseek,
.release = seq_release_private,
};
#define INF(NAME, MODE, read)
NOD(NAME, (S_IFREG|(MODE)),
NULL, &proc_info_file_operations,
{ .proc_read = read } )
static const struct file_operations proc_info_file_operations = {-------->支持信息读取
.read = proc_info_read,
.llseek = generic_file_llseek,
};
例子: INF("cmdline", S_IRUGO, proc_pid_cmdline),
-r--r--r-- root root 0 2014-01-01 12:00 cmdline
#define ONE(NAME, MODE, show) --------->单个文件?什么意思?
NOD(NAME, (S_IFREG|(MODE)),
NULL, &proc_single_file_operations,
{ .proc_show = show } )-------->填充的是proc_show,可以看出ONE,INFO,LINK等的其中一个差别就是设置prop_op 不一样,另外一个是file_operation不一样
例子:
#ifdef CONFIG_STACKTRACE
ONE("stack", S_IRUGO, proc_pid_stack),
#endif
-r--r--r-- root root 0 2014-01-01 12:07 stack 只读信息
/* ANDROID is for special files in /proc. */ --------------------------->还冒出来一个android相关的
#define ANDROID(NAME, MODE, OTYPE)
NOD(NAME, (S_IFREG|(MODE)),
&proc_##OTYPE##_inode_operations,
&proc_##OTYPE##_operations, {})
例子:
ANDROID("oom_adj",S_IRUGO|S_IWUSR, oom_adjust), ----------------->调整优先级,我们的service,activity 相关的进程分前端,后端优先级不一样会动态调整,不知道是不是通过这个调整的?有一个特别的地方是具体有写权限。
-rw-r--r-- root root 0 2014-01-01 12:07 oom_adj
union proc_op {------------------------------------------------------------->联合体,同时只会存在一种可能。
int (*proc_get_link)(struct inode *, struct path *);
int (*proc_read)(struct task_struct *task, char *page);
int (*proc_show)(struct seq_file *m,
struct pid_namespace *ns, struct pid *pid,
struct task_struct *task);
};
下面详细查看maps 相关的实现内容
代码位置:
android/linux-3.0.86/fs/proc/task_mmu.c
-
const struct file_operations proc_maps_operations = {
-
.open = maps_open,
-
.read = seq_read,
-
.llseek = seq_lseek,
-
.release = seq_release_private,
-
};
使用strace 跟踪一下cat maps 的执行情况:
-
1|shell@tiny4412:/proc/1 # strace cat maps
-
execve("/system/bin/cat", ["cat", "maps"], [/* 24 vars */]) = 0
-
mprotect(0x401db000, 4096, PROT_READ) = 0
-
set_tid_address(0x401dced0) = 10588
-
set_tls(0x401dd10c, 0x401dd10c, 0x401dd10c, 0x401dcedc, 0x401dcec8) = 0
-
mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40027000
-
madvise(0x40027000, 8192, MADV_MERGEABLE) = -1 EINVAL (Invalid argument)
-
sigaltstack({ss_sp=0x40027000, ss_flags=0, ss_size=8192}, NULL) = 0
-
sigaction(SIGABRT, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGBUS, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGFPE, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGILL, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGPIPE, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGSEGV, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGSTKFLT, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
sigaction(SIGTRAP, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x4009e000
-
prctl(0x53564d41 /* PR_??? */, 0, 0x4009e000, 0x1000, 0x401d87ca) = -1 EINVAL (Invalid argument)
-
openat(AT_FDCWD, "/vendor/lib/libsigchain.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libsigchain.so", O_RDONLY) = 3
-
fstat64(3, {st_mode=S_IFREG|0644, st_size=5352, ...}) = 0
-
read(3, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40100000
-
mmap2(NULL, 12288, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x401de000
-
mmap2(0x401de000, 2953, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x401de000
-
mmap2(0x401df000, 4100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x401df000
-
openat(AT_FDCWD, "/vendor/lib/libc.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libc.so", O_RDONLY) = 4
-
fstat64(4, {st_mode=S_IFREG|0644, st_size=608820, ...}) = 0
-
read(4, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 4, 0) = 0x40067000
-
mmap2(NULL, 483328, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40143000
-
mmap2(0x40143000, 414868, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4, 0) = 0x40143000
-
mmap2(0x401aa000, 21808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x66000) = 0x401aa000
-
mmap2(0x401b0000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x401b0000
-
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x40101000
-
prctl(0x53564d41 /* PR_??? */, 0, 0x40101000, 0x1000, 0x401d87ca) = -1 EINVAL (Invalid argument)
-
mprotect(0x401aa000, 12288, PROT_READ) = 0
-
munmap(0x40067000, 4096) = 0
-
close(4) = 0
-
openat(AT_FDCWD, "/vendor/lib/liblog.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/liblog.so", O_RDONLY) = 4
-
fstat64(4, {st_mode=S_IFREG|0644, st_size=21744, ...}) = 0
-
read(4, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 4, 0) = 0x40042000
-
mmap2(NULL, 28672, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4006d000
-
mmap2(0x4006d000, 16860, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4, 0) = 0x4006d000
-
mmap2(0x40072000, 4108, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x4000) = 0x40072000
-
openat(AT_FDCWD, "/vendor/lib/libm.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libm.so", O_RDONLY) = 5
-
fstat64(5, {st_mode=S_IFREG|0644, st_size=95508, ...}) = 0
-
read(5, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 5, 0) = 0x40074000
-
mmap2(NULL, 102400, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40122000
-
mmap2(0x40122000, 90404, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 5, 0) = 0x40122000
-
mmap2(0x40139000, 4204, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 5, 0x16000) = 0x40139000
-
mprotect(0x40139000, 4096, PROT_READ) = 0
-
munmap(0x40074000, 4096) = 0
-
close(5) = 0
-
openat(AT_FDCWD, "/vendor/lib/libstdc++.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libstdc++.so", O_RDONLY) = 5
-
fstat64(5, {st_mode=S_IFREG|0644, st_size=9396, ...}) = 0
-
read(5, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 5, 0) = 0x40021000
-
mmap2(NULL, 16384, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40074000
-
mmap2(0x40074000, 5782, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 5, 0) = 0x40074000
-
mmap2(0x40076000, 4100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 5, 0x1000) = 0x40076000
-
mprotect(0x40076000, 4096, PROT_READ) = 0
-
munmap(0x40021000, 4096) = 0
-
close(5) = 0
-
mprotect(0x40072000, 4096, PROT_READ) = 0
-
munmap(0x40042000, 4096) = 0
-
close(4) = 0
-
mprotect(0x401df000, 4096, PROT_READ) = 0
-
munmap(0x40100000, 4096) = 0
-
close(3) = 0
-
openat(AT_FDCWD, "/vendor/lib/libcrypto.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libcrypto.so", O_RDONLY) = 3
-
fstat64(3, {st_mode=S_IFREG|0644, st_size=1052960, ...}) = 0
-
read(3, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4003a000
-
mmap2(NULL, 1064960, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x401e1000
-
mmap2(0x401e1000, 966164, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x401e1000
-
mmap2(0x402ce000, 84864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xec000) = 0x402ce000
-
mmap2(0x402e3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x402e3000
-
mprotect(0x402ce000, 61440, PROT_READ) = 0
-
munmap(0x4003a000, 4096) = 0
-
close(3) = 0
-
openat(AT_FDCWD, "/vendor/lib/libcutils.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libcutils.so", O_RDONLY) = 3
-
fstat64(3, {st_mode=S_IFREG|0644, st_size=46480, ...}) = 0
-
read(3, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40098000
-
mmap2(NULL, 53248, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40102000
-
mmap2(0x40102000, 42896, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x40102000
-
mmap2(0x4010d000, 4160, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xa000) = 0x4010d000
-
mprotect(0x4010d000, 4096, PROT_READ) = 0
-
munmap(0x40098000, 4096) = 0
-
close(3) = 0
-
openat(AT_FDCWD, "/vendor/lib/libselinux.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libselinux.so", O_RDONLY) = 3
-
fstat64(3, {st_mode=S_IFREG|0644, st_size=50564, ...}) = 0
-
read(3, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x400dc000
-
mmap2(NULL, 57344, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x402e5000
-
mmap2(0x402e5000, 47462, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x402e5000
-
mmap2(0x402f1000, 4144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xb000) = 0x402f1000
-
mprotect(0x402f1000, 4096, PROT_READ) = 0
-
munmap(0x400dc000, 4096) = 0
-
close(3) = 0
-
mprotect(0x400dd000, 4096, PROT_READ) = 0
-
openat(AT_FDCWD, "/dev/__properties__", O_RDONLY|O_NOFOLLOW) = 3--------------->打开文件
-
fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
-
fstat64(3, {st_mode=S_IFREG|0444, st_size=131072, ...}) = 0
-
mmap2(NULL, 131072, PROT_READ, MAP_SHARED, 3, 0) = 0x402f3000
-
close(3) = 0
-
futex(0x401af5a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
openat(AT_FDCWD, "/vendor/lib/libnetd_client.so", O_RDONLY) = -1 ENOENT (No such file or directory)
-
openat(AT_FDCWD, "/system/lib/libnetd_client.so", O_RDONLY) = 3
-
fstat64(3, {st_mode=S_IFREG|0644, st_size=9428, ...}) = 0
-
read(3, "177ELF111 3 ( 1 004 "..., 52) = 52
-
mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x400dc000
-
mmap2(NULL, 16384, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4010f000
-
mmap2(0x4010f000, 3856, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x4010f000
-
mmap2(0x40111000, 4100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0x40111000
-
mprotect(0x40111000, 4096, PROT_READ) = 0
-
munmap(0x400dc000, 4096) = 0
-
close(3) = 0
-
mprotect(0x4009e000, 4096, PROT_READ) = 0
-
mprotect(0x40101000, 4096, PROT_READ) = 0
-
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x40046000
-
prctl(0x53564d41 /* PR_??? */, 0, 0x40046000, 0x1000, 0x401d87ca) = -1 EINVAL (Invalid argument)
-
futex(0x401b0dd4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
brk(0) = 0x41525000
-
mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40313000
-
madvise(0x40313000, 1048576, MADV_MERGEABLE) = -1 EINVAL (Invalid argument)
-
prctl(0x53564d41 /* PR_??? */, 0, 0x40313000, 0x100000, 0x401a1685) = -1 EINVAL (Invalid argument)
-
munmap(0x40313000, 1048576) = 0
-
mmap2(NULL, 2093056, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40313000
-
prctl(0x53564d41 /* PR_??? */, 0, 0x40313000, 0x1ff000, 0x401a1685) = -1 EINVAL (Invalid argument)
-
munmap(0x40313000, 970752) = 0
-
munmap(0x40500000, 73728) = 0
-
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40100000
-
mprotect(0x40100000, 4096, PROT_READ) = 0
-
openat(AT_FDCWD, "/proc/stat", O_RDONLY) = 3 ----------------------->打开文件
-
fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
-
mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40500000
-
prctl(0x53564d41 /* PR_??? */, 0, 0x40500000, 0x100000, 0x401a1685) = -1 EINVAL (Invalid argument)
-
mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40100000, 4096, PROT_READ) = 0
-
read(3, "cpu 5457 1230 13251 421214 1598"..., 1024) = 1024
-
read(3, " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"..., 1024) = 212
-
read(3, "", 1024) = 0
-
close(3) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
statfs64("/sys/fs/selinux", 88, {f_type=0xf97cff8c, f_bsize=4096, f_blocks=0, f_bfree=0, f_bavail=0, f_files=0, f_ffree=0, f_fsid={0, 0}, f_namelen=255, f_frsize=4096, f_flags=4128}) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
rt_sigprocmask(SIG_SETMASK, [HUP INT QUIT ABRT KILL USR1 USR2 PIPE ALRM TERM STKFLT CHLD CONT STOP TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS RTMIN], [], 8) = 0
-
sigaction(SIGILL, {0x402a3b6d, ~[ILL TRAP BUS FPE SEGV], 0}, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}) = 0
-
rt_sigprocmask(SIG_BLOCK, [], [HUP INT QUIT ABRT USR1 USR2 PIPE ALRM TERM STKFLT CHLD CONT TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS RTMIN], 8) = 0
-
--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPC, si_addr=0x40223908} ---
-
rt_sigprocmask(SIG_SETMASK, [HUP INT QUIT ABRT USR1 USR2 PIPE ALRM TERM STKFLT CHLD CONT TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS RTMIN], [HUP INT QUIT ILL ABRT USR1 USR2 PIPE ALRM TERM 0
-
sigaction(SIGILL, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
-
rt_sigprocmask(SIG_SETMASK, [], [HUP INT QUIT ABRT USR1 USR2 PIPE ALRM TERM STKFLT CHLD CONT TSTP TTIN TTOU URG XCPU XFSZ VTALRM PROF WINCH IO PWR SYS RTMIN], 8) = 0
-
mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x4009e000, 4096, PROT_READ) = 0
-
mprotect(0x40101000, 4096, PROT_READ) = 0
-
mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40100000, 4096, PROT_READ) = 0
-
-
openat(AT_FDCWD, "maps", O_RDONLY) = 3 ----------->打开maps文件
-
------------------------------------------------------------------------------------------------------------------------>这一块都是输出了
-
-
fstat64(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(204, 64), ...}) = 0
-
read(3, "00008000-00049000 r-xp 00000000 "..., 4096) = 570
-
write(1, "00008000-00049000 r-xp 00000000 "..., 57000008000-00049000 r-xp 00000000 00:01 1422 /init
-
0004a000-0004c000 r--p 00041000 00:01 1422 /init
-
0004c000-0004f000 rw-p 00043000 00:01 1422 /init
-
0004f000-00052000 rw-p 00000000 00:00 0 [heap]
-
40017000-40019000 rw-p 00000000 00:00 0
-
40072000-40073000 r--p 00000000 00:00 0
-
40090000-400b0000 rw-s 00000000 00:0c 2056 /dev/__properties__
-
400b2000-400b3000 rw-p 00000000 00:00 0
-
40100000-40301000 rw-p 00000000 00:00 0
-
becd2000-becf3000 rw-p 00000000 00:00 0 [stack]
-
ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
-
) = 570
-
read(3, "", 4096) = 0
-
close(3) = 0
-
close(1) = 0
-
mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40100000, 4096, PROT_READ) = 0
-
close(0) = 0
-
close(2) = 0
-
futex(0x401af5a0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
-
mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
-
mprotect(0x40100000, 4096, PROT_READ) = 0
-
munmap(0x40100000, 4096) = 0
-
exit_group(0) = ?
-
+++ exited with 0 +++
跟踪源码,先看一下maps_open
-
static int maps_open(struct inode *inode, struct file *file)
-
{
-
return do_maps_open(inode, file, &proc_pid_maps_op); ----------->填充了proc_pid_maps_op的操作,序列文件的op
-
}
-
static const struct seq_operations proc_pid_maps_op = {
-
.start = m_start,
-
.next = m_next,
-
.stop = m_stop,
-
.show = show_map
-
};
-
static int do_maps_open(struct inode *inode, struct file *file,
-
const struct seq_operations *ops)
-
{
-
struct proc_maps_private *priv;
-
int ret = -ENOMEM;
-
priv = kzalloc(sizeof(*priv), GFP_KERNEL);--------->分配memory?
-
if (priv) {
-
priv->pid = proc_pid(inode);-------->通过inode获取pid信息
-
ret = seq_open(file, ops);------------->打开序列文件
-
if (!ret) {
-
struct seq_file *m = file->private_data;
-
m->private = priv;
-
} else {
-
kfree(priv);
-
}
-
}
-
return ret;
-
}
proc_maps_private 为何物?
-
struct proc_maps_private {
-
struct pid *pid;-------------------->仅仅一个pid并不简单,不能跟太深,会迷失...
-
struct task_struct *task;--------->进程相关的信息
-
-
struct vm_area_struct *tail_vma;
-
-
};
-
static inline struct pid *proc_pid(struct inode *inode)
-
{
-
return PROC_I(inode)->pid;------------->根据inode可以找到对应的进程id
-
}
-
static inline struct proc_inode *PROC_I(const struct inode *inode)
-
{
-
return container_of(inode, struct proc_inode, vfs_inode);
-
}
通过inode 进而找到proc_inode,然后再找到pid
-
struct proc_inode {
-
struct pid *pid;--------------------->找到了....
-
int fd;
-
union proc_op op;
-
struct proc_dir_entry *pde;
-
struct ctl_table_header *sysctl;
-
struct ctl_table *sysctl_entry;
-
void *ns;
-
const struct proc_ns_operations *ns_ops;
-
struct inode vfs_inode;------------------->知道地之后,计算偏移,就可以找到pid了
-
};
序列文件?
-
int seq_open(struct file *file, const struct seq_operations *op)
-
{
-
struct seq_file *p = file->private_data; ---------->难道数据存储在file的private_data,什么时候第一次生成的呢?理论上该是在进程创建的时候。
-
-
if (!p) {
-
p = kmalloc(sizeof(*p), GFP_KERNEL);---------》如果为空,那么就分配一个,并将地址存放到file的似有空间里面。
-
if (!p)
-
return -ENOMEM;
-
file->private_data = p;
-
}
-
memset(p, 0, sizeof(*p));
-
mutex_init(&p->lock);
-
p->op = op;----------------------------->填充之前传进来的proc_pid_maps_op, 即使是空的,也就是至少准备了一个seq_file
-
-
/*
-
* Wrappers around seq_open(e.g. swaps_open) need to be
-
* aware of this. If they set f_version themselves, they
-
* should call seq_open first and then set f_version.
-
*/
-
file->f_version = 0;
-
-
/*
-
* seq_files support lseek() and pread(). They do not implement
-
* write() at all, but we clear FMODE_PWRITE here for historical
-
* reasons.
-
*
-
* If a client of seq_files a) implements file.write() and b) wishes to
-
* support pwrite() then that client will need to implement its own
-
* file.open() which calls seq_open() and then sets FMODE_PWRITE.
-
*/
-
file->f_mode &= ~FMODE_PWRITE;
-
return 0;
-
}
看一下seq_file到底是什么样子?
-
struct seq_file {
-
char *buf;
-
size_t size;
-
size_t from;
-
size_t count;
-
loff_t index;
-
loff_t read_pos;
-
u64 version;
-
struct mutex lock;
-
const struct seq_operations *op;
-
void *private;
-
};
感觉就是一段buffer,然后增加了版本,代写哦啊,偏移位置,锁以及ops等信息
那么接下来应该是读取了?因为理论上应该是先open,然后读取的
-
ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
-
{
-
struct seq_file *m = file->private_data; -------------->不知道这个数据是不是空的啊?现在应该不是空的了,上面已经填充了...
-
size_t copied = 0;
-
loff_t pos;
-
size_t n;
-
void *p;
-
int err = 0;
-
-
mutex_lock(&m->lock);
-
-
/* Don't assume *ppos is where we left it */
-
if (unlikely(*ppos != m->read_pos)) {
-
m->read_pos = *ppos;
-
while ((err = traverse(m, *ppos)) == -EAGAIN) ---------------->1. 做什么?
-
;
-
if (err) {
-
/* With prejudice... */
-
m->read_pos = 0;
-
m->version = 0;
-
m->index = 0;
-
m->count = 0;
-
goto Done;
-
}
-
}
-
-
/*
-
* seq_file->op->..m_start/m_stop/m_next may do special actions
-
* or optimisations based on the file->f_version, so we want to
-
* pass the file->f_version to those methods.
-
*
-
* seq_file->version is just copy of f_version, and seq_file
-
* methods can treat it simply as file version.
-
* It is copied in first and copied out after all operations.
-
* It is convenient to have it as part of structure to avoid the
-
* need of passing another argument to all the seq_file methods.
-
*/
-
m->version = file->f_version;
-
/* grab buffer if we didn't have one */
-
if (!m->buf) {
-
m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
-
if (!m->buf)
-
goto Enomem;
-
}
-
/* if not empty - flush it first */
-
if (m->count) {
-
n = min(m->count, size);
-
err = copy_to_user(buf, m->buf + m->from, n);
-
if (err)
-
goto Efault;
-
m->count -= n;
-
m->from += n;
-
size -= n;
-
buf += n;
-
copied += n;
-
if (!m->count)
-
m->index++;
-
if (!size)
-
goto Done;
-
}
-
/* we need at least one record in buffer */
-
pos = m->index;
-
p = m->op->start(m, &pos);
-
while (1) {
-
err = PTR_ERR(p);
-
if (!p || IS_ERR(p))
-
break;
-
err = m->op->show(m, p); ------------->显示?
-
if (err < 0)
-
break;
-
if (unlikely(err))
-
m->count = 0;
-
if (unlikely(!m->count)) {
-
p = m->op->next(m, p, &pos);
-
m->index = pos;
-
continue;
-
}
-
if (m->count < m->size)
-
goto Fill;
-
m->op->stop(m, p);
-
kfree(m->buf);
-
m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
-
if (!m->buf)
-
goto Enomem;
-
m->count = 0;
-
m->version = 0;
-
pos = m->index;
-
p = m->op->start(m, &pos);
-
}
-
m->op->stop(m, p);
-
m->count = 0;
-
goto Done;
-
Fill:
-
/* they want more? let's try to get some more */
-
while (m->count < size) {
-
size_t offs = m->count;
-
loff_t next = pos;
-
p = m->op->next(m, p, &next);
-
if (!p || IS_ERR(p)) {
-
err = PTR_ERR(p);
-
break;
-
}
-
err = m->op->show(m, p);
-
if (m->count == m->size || err) {
-
m->count = offs;
-
if (likely(err <= 0))
-
break;
-
}
-
pos = next;
-
}
-
m->op->stop(m, p);
-
n = min(m->count, size);
-
err = copy_to_user(buf, m->buf, n);
-
if (err)
-
goto Efault;
-
copied += n;
-
m->count -= n;
-
if (m->count)
-
m->from = n;
-
else
-
pos++;
-
m->index = pos;
-
Done:
-
if (!copied)
-
copied = err;
-
else {
-
*ppos += copied;
-
m->read_pos += copied;
-
}
-
file->f_version = m->version;
-
mutex_unlock(&m->lock);
-
return copied;
-
Enomem:
-
err = -ENOMEM;
-
goto Done;
-
Efault:
-
err = -EFAULT;
-
goto Done;
-
}
-
EXPORT_SYMBOL(seq_read);
traverse 做了什么呢?
-
static int traverse(struct seq_file *m, loff_t offset)
-
{
-
loff_t pos = 0, index;
-
int error = 0;
-
void *p;
-
-
m->version = 0;
-
index = 0;
-
m->count = m->from = 0;
-
if (!offset) {
-
m->index = index;
-
return 0;
-
}
-
if (!m->buf) { ---------------->这个都不知道是不是空的?
-
m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
-
if (!m->buf)
-
return -ENOMEM;
-
}
-
p = m->op->start(m, &index);-----------调用m_start,是准备什么吗?
-
while (p) {
-
error = PTR_ERR(p);
-
if (IS_ERR(p))
-
break;
-
error = m->op->show(m, p);
-
if (error < 0)
-
break;
-
if (unlikely(error)) {
-
error = 0;
-
m->count = 0;
-
}
-
if (m->count == m->size)
-
goto Eoverflow;
-
if (pos + m->count > offset) {
-
m->from = offset - pos;
-
m->count -= m->from;
-
m->index = index;
-
break;
-
}
-
pos += m->count;
-
m->count = 0;
-
if (pos == offset) {
-
index++;
-
m->index = index;
-
break;
-
}
-
p = m->op->next(m, p, &index);
-
}
-
m->op->stop(m, p);
-
m->index = index;
-
return error;
-
-
Eoverflow:
-
m->op->stop(m, p);
-
kfree(m->buf);
-
m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
-
return !m->buf ? -ENOMEM : -EAGAIN;
-
}
m_start 做了什么?
-
static void *m_start(struct seq_file *m, loff_t *pos)
-
{
-
struct proc_maps_private *priv = m->private;
-
unsigned long last_addr = m->version;
-
struct mm_struct *mm;
-
struct vm_area_struct *vma, *tail_vma = NULL;
-
loff_t l = *pos;
-
-
/* Clear the per syscall fields in priv */
-
priv->task = NULL;
-
priv->tail_vma = NULL;
-
-
/*
-
* We remember last_addr rather than next_addr to hit with
-
* mmap_cache most of the time. We have zero last_addr at
-
* the beginning and also after lseek. We will have -1 last_addr
-
* after the end of the vmas.
-
*/
-
-
if (last_addr == -1UL)
-
return NULL;
-
-
priv->task = get_pid_task(priv->pid, PIDTYPE_PID); ---------->通过pid 获取到task_struct
-
if (!priv->task)
-
return ERR_PTR(-ESRCH);
-
-
mm = mm_for_maps(priv->task);------------->这个看着很关键。。。,其实就是进行了权限检测,并得到了mm指针
-
if (!mm || IS_ERR(mm))
-
return mm;
-
down_read(&mm->mmap_sem);
-
-
tail_vma = get_gate_vma(priv->task->mm); ---------->获取vma的结束位置
-
priv->tail_vma = tail_vma;
-
-
/* Start with last addr hint */
-
vma = find_vma(mm, last_addr);-------------->从红黑树中得到对应的虚拟地址区域
-
if (last_addr && vma) {
-
vma = vma->vm_next;
-
goto out;
-
}
-
-
/*
-
* Check the vma index is within the range and do
-
* sequential scan until m_index.
-
*/
-
vma = NULL;
-
if ((unsigned long)l < mm->map_count) {
-
vma = mm->mmap;
-
while (l-- && vma)
-
vma = vma->vm_next;
-
goto out;
-
}
-
-
if (l != mm->map_count)
-
tail_vma = NULL; /* After gate vma */
-
-
out:
-
if (vma)
-
return vma;
-
-
/* End of vmas has been reached */
-
m->version = (tail_vma != NULL)? 0: -1UL;
-
up_read(&mm->mmap_sem);
-
mmput(mm); -------------->释放对mm的使用记录
-
return tail_vma;
-
}
-
struct mm_struct *mm_for_maps(struct task_struct *task)
-
{
-
return mm_access(task, PTRACE_MODE_READ);------------>看着像是ptrace实现的额?
-
}
-
static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
-
{
-
struct mm_struct *mm;
-
int err;
-
-
err = mutex_lock_killable(&task->signal->cred_guard_mutex);
-
if (err)
-
return ERR_PTR(err);
-
-
mm = get_task_mm(task); -------------->通过task_struct 获取mm_struct结构,并且增加对mm_struct 使用的计数
-
if (mm && mm != current->mm &&
-
!ptrace_may_access(task, mode) && --------------->对进程进行跟踪,这里会进行严格的权限检测
-
!capable(CAP_SYS_RESOURCE)) {
-
mmput(mm);
-
mm = ERR_PTR(-EACCES);
-
}
-
mutex_unlock(&task->signal->cred_guard_mutex);
-
-
return mm;
-
}
总结m_start 所做的事情,也就是说traverse找到了对应的vm_area_struct
pid-->task_struct->mm_struct->vm_area_struct
接下来就要调用show_map
-
static int show_map(struct seq_file *m, void *v)
-
{
-
struct vm_area_struct *vma = v;
-
struct proc_maps_private *priv = m->private;
-
struct task_struct *task = priv->task;
-
-
show_map_vma(m, vma);-------->显示vma 区域
-
-
if (m->count < m->size) /* vma is copied successfully */
-
m->version = (vma != get_gate_vma(task->mm))
-
? vma->vm_start : 0;
-
return 0;
-
}
-
static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
-
{
-
struct mm_struct *mm = vma->vm_mm;
-
struct file *file = vma->vm_file;
-
vm_flags_t flags = vma->vm_flags;
-
unsigned long ino = 0;
-
unsigned long long pgoff = 0;
-
unsigned long start, end;
-
dev_t dev = 0;
-
int len;
-
-
if (file) {
-
struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
-
dev = inode->i_sb->s_dev;
-
ino = inode->i_ino;
-
pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
-
}
-
-
/* We don't show the stack guard page in /proc/maps */
-
start = vma->vm_start;
-
if (stack_guard_page_start(vma, start)) -------->可以查看到该区域的增长是向下,还是向上的...
-
start += PAGE_SIZE;
-
end = vma->vm_end;
-
if (stack_guard_page_end(vma, end))
-
end -= PAGE_SIZE;
-
-
seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
-
start,
-
end,
-
flags & VM_READ ? 'r' : '-',
-
flags & VM_WRITE ? 'w' : '-',
-
flags & VM_EXEC ? 'x' : '-',
-
flags & VM_MAYSHARE ? 's' : 'p',
-
pgoff,
-
MAJOR(dev), MINOR(dev), ino, &len);------------>关键的一句输出
-
-
-
/*
-
* Print the dentry name for named mappings, and a
-
* special [heap] marker for the heap:
-
*/
-
if (file) {
-
pad_len_spaces(m, len);
-
seq_path(m, &file->f_path, " ");
-
} else {
-
const char *name = arch_vma_name(vma);
-
if (!name) {
-
if (mm) {
-
if (vma->vm_start <= mm->brk &&
-
vma->vm_end >= mm->start_brk) { ------------>堆的区域
-
name = "[heap]";
-
} else if (vma->vm_start <= mm->start_stack &&
-
vma->vm_end >= mm->start_stack) {------------->栈的区域
-
name = "[stack]";
-
}
-
} else {
-
name = "[vdso]";
-
}
-
}
-
if (name) {
-
pad_len_spaces(m, len);
-
seq_puts(m, name);
-
}
-
}
-
seq_putc(m, ' ');
-
}
详细看一下mm_struct的几个成员:
-
unsigned long total_vm, locked_vm, shared_vm, exec_vm;
-
unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
-
unsigned long start_code, end_code, start_data, end_data;
-
unsigned long start_brk, brk, start_stack;
-
unsigned long arg_start, arg_end, env_start, env_end;
-
-
unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
-
-
/*
-
* Special counters, in some configurations protected by the
-
* page_table_lock, in other configurations by being atomic.
-
*/
-
struct mm_rss_stat rss_stat;
图片源自http://blog.csdn.net/dyllove98/article/details/8917197
参考:http://blog.csdn.net/dyllove98/article/details/8917197