• /proc/N/maps 信息是如何生成的?【转】


    转自:https://blog.csdn.net/zhoukangli/article/details/53363275?utm_medium=distribute.pc_relevant_bbs_down.none-task-blog-baidujs-1.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task-blog-baidujs-1.nonecase

    以进程1为例,查看proc长什么样子?

    1. 127|shell@tiny4412:/proc/1 # ls -l
    2. dr-xr-xr-x root root 2014-01-01 12:07 attr
    3. -r-------- root root 0 2014-01-01 12:07 auxv
    4. -r--r--r-- root root 0 2014-01-01 12:07 cgroup
    5. --w------- root root 0 2014-01-01 12:07 clear_refs
    6. -r--r--r-- root root 0 2014-01-01 12:00 cmdline
    7. -rw-r--r-- root root 0 2014-01-01 12:07 comm
    8. -rw-r--r-- root root 0 2014-01-01 12:07 coredump_filter
    9. lrwxrwxrwx root root 2014-01-01 12:07 cwd -> /
    10. -r-------- root root 0 2014-01-01 12:07 environ
    11. lrwxrwxrwx root root 2014-01-01 12:07 exe -> /init
    12. dr-x------ root root 2014-01-01 12:07 fd
    13. dr-x------ root root 2014-01-01 12:07 fdinfo
    14. -r--r--r-- root root 0 2014-01-01 12:07 limits
    15. -rw-r--r-- root root 0 2014-01-01 12:07 loginuid
    16. -r--r--r-- root root 0 2014-01-01 12:07 maps ----------->比较关心映射关系是如何生成的
    17. -rw------- root root 0 2014-01-01 12:07 mem
    18. -r--r--r-- root root 0 2014-01-01 12:07 mountinfo
    19. -r--r--r-- root root 0 2014-01-01 12:07 mounts
    20. -r-------- root root 0 2014-01-01 12:07 mountstats
    21. dr-xr-xr-x root root 2014-01-01 12:00 net
    22. dr-x--x--x root root 2014-01-01 12:07 ns
    23. -rw-r--r-- root root 0 2014-01-01 12:07 oom_adj
    24. -r--r--r-- root root 0 2014-01-01 12:07 oom_killed
    25. -r--r--r-- root root 0 2014-01-01 12:07 oom_score
    26. -rw-r--r-- root root 0 2014-01-01 12:00 oom_score_adj
    27. -r--r--r-- root root 0 2014-01-01 12:07 pagemap
    28. -r--r--r-- root root 0 2014-01-01 12:07 personality
    29. lrwxrwxrwx root root 2014-01-01 12:07 root -> /
    30. -rw-r--r-- root root 0 2014-01-01 12:07 sched
    31. -r--r--r-- root root 0 2014-01-01 12:07 schedstat
    32. -r--r--r-- root root 0 2014-01-01 12:07 sessionid
    33. -r--r--r-- root root 0 2014-01-01 12:00 smaps
    34. -r--r--r-- root root 0 2014-01-01 12:07 stack
    35. -r--r--r-- root root 0 2014-01-01 12:00 stat
    36. -r--r--r-- root root 0 2014-01-01 12:07 statm
    37. -r--r--r-- root root 0 2014-01-01 12:07 status
    38. dr-xr-xr-x root root 2014-01-01 12:00 task
    39. -r--r--r-- root root 0 2014-01-01 12:07 wchan

    查看详细映射关系:

    1. shell@tiny4412:/proc/1 # cat maps
    2. 00008000-00049000 r-xp 00000000 00:01 1422 /init
    3. 0004a000-0004c000 r--p 00041000 00:01 1422 /init
    4. 0004c000-0004f000 rw-p 00043000 00:01 1422 /init
    5. 0004f000-00052000 rw-p 00000000 00:00 0 [heap]
    6. 40017000-40019000 rw-p 00000000 00:00 0
    7. 40072000-40073000 r--p 00000000 00:00 0
    8. 40090000-400b0000 rw-s 00000000 00:0c 2056 /dev/__properties__
    9. 400b2000-400b3000 rw-p 00000000 00:00 0
    10. 40100000-40301000 rw-p 00000000 00:00 0
    11. becd2000-becf3000 rw-p 00000000 00:00 0 [stack]
    12. ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
    13.  
    14. 根据源码的解析:
    15. vm_area_struct
    16.     unsigned long vm_start;        /* Our start address within vm_mm. */
    17.     unsigned long vm_end;        /* The first byte after our end address
    18.                        within vm_mm. */
    19.     unsigned long vm_flags;        /* Flags, see mm.h. */ 分别是读,写,共享/私有
    20.     /* Information about our backing store: */
    21.     unsigned long vm_pgoff;        /* Offset (within vm_file) in PAGE_SIZE 页偏移
    22.                        units, *not* PAGE_CACHE_SIZE */
    23.  
    24. vma->vm_file->f_path.dentry->d_inode-->i_sb->s_dev; 主设备号,次设备号
    1. vma->vm_file->f_path.dentry->d_inode-->i_ino inode 号
    2. 最后就是    /*
    3.      * Print the dentry name for named mappings, and a
    4.      * special [heap] marker for the heap:
    5.      */调用文件路径
    6.  

    linux源码位置及主要宏

    android/linux-3.0.86/fs/proc/base.c

    1. static const struct pid_entry tid_base_stuff[] = {
    2. DIR("fd", S_IRUSR|S_IXUSR, proc_fd_inode_operations, proc_fd_operations),
    3. DIR("fdinfo", S_IRUSR|S_IXUSR, proc_fdinfo_inode_operations, proc_fdinfo_operations),
    4. DIR("ns", S_IRUSR|S_IXUGO, proc_ns_dir_inode_operations, proc_ns_dir_operations),
    5. REG("environ", S_IRUSR, proc_environ_operations),
    6. INF("auxv", S_IRUSR, proc_pid_auxv),
    7. ONE("status", S_IRUGO, proc_pid_status),
    8. ONE("personality", S_IRUGO, proc_pid_personality),
    9. INF("limits", S_IRUGO, proc_pid_limits),
    10. #ifdef CONFIG_SCHED_DEBUG
    11. REG("sched", S_IRUGO|S_IWUSR, proc_pid_sched_operations),
    12. #endif
    13. REG("comm", S_IRUGO|S_IWUSR, proc_pid_set_comm_operations),
    14. #ifdef CONFIG_HAVE_ARCH_TRACEHOOK
    15. INF("syscall", S_IRUGO, proc_pid_syscall),
    16. #endif
    17. INF("cmdline", S_IRUGO, proc_pid_cmdline),
    18. ONE("stat", S_IRUGO, proc_tid_stat),
    19. ONE("statm", S_IRUGO, proc_pid_statm),
    20. REG("maps", S_IRUGO, proc_maps_operations), -------------------->关注映射
    21. #ifdef CONFIG_NUMA
    22. REG("numa_maps", S_IRUGO, proc_numa_maps_operations),
    23. #endif
    24. REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations),
    25. LNK("cwd", proc_cwd_link),
    26. LNK("root", proc_root_link),
    27. LNK("exe", proc_exe_link),
    28. REG("mounts", S_IRUGO, proc_mounts_operations),
    29. REG("mountinfo", S_IRUGO, proc_mountinfo_operations),
    30. #ifdef CONFIG_PROC_PAGE_MONITOR
    31. REG("clear_refs", S_IWUSR, proc_clear_refs_operations),
    32. REG("smaps", S_IRUGO, proc_smaps_operations),
    33. REG("pagemap", S_IRUGO, proc_pagemap_operations),
    34. #endif
    35. #ifdef CONFIG_SECURITY
    36. DIR("attr", S_IRUGO|S_IXUGO, proc_attr_dir_inode_operations, proc_attr_dir_operations),
    37. #endif
    38. #ifdef CONFIG_KALLSYMS
    39. INF("wchan", S_IRUGO, proc_pid_wchan),
    40. #endif
    41. #ifdef CONFIG_STACKTRACE
    42. ONE("stack", S_IRUGO, proc_pid_stack),
    43. #endif
    44. #ifdef CONFIG_SCHEDSTATS
    45. INF("schedstat", S_IRUGO, proc_pid_schedstat),
    46. #endif
    47. #ifdef CONFIG_LATENCYTOP
    48. REG("latency", S_IRUGO, proc_lstats_operations),
    49. #endif
    50. #ifdef CONFIG_PROC_PID_CPUSET
    51. REG("cpuset", S_IRUGO, proc_cpuset_operations),
    52. #endif
    53. #ifdef CONFIG_CGROUPS
    54. REG("cgroup", S_IRUGO, proc_cgroup_operations),
    55. #endif
    56. INF("oom_score", S_IRUGO, proc_oom_score),
    57. REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations),
    58. REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations),
    59. #ifdef CONFIG_ANDROID
    60. REG("oom_killed", S_IRUGO, proc_oom_killed_operations),
    61. #endif
    62. #ifdef CONFIG_AUDITSYSCALL
    63. REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations),
    64. REG("sessionid", S_IRUGO, proc_sessionid_operations),
    65. #endif
    66. #ifdef CONFIG_FAULT_INJECTION
    67. REG("make-it-fail", S_IRUGO|S_IWUSR, proc_fault_inject_operations),
    68. #endif
    69. #ifdef CONFIG_TASK_IO_ACCOUNTING
    70. INF("io", S_IRUSR, proc_tid_io_accounting),
    71. #endif
    72. #ifdef CONFIG_HARDWALL
    73. INF("hardwall", S_IRUGO, proc_pid_hardwall),
    74. #endif
    75. };


    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

    1. const struct file_operations proc_maps_operations = {
    2. .open = maps_open,
    3. .read = seq_read,
    4. .llseek = seq_lseek,
    5. .release = seq_release_private,
    6. };

    使用strace 跟踪一下cat maps 的执行情况:

    1. 1|shell@tiny4412:/proc/1 # strace cat maps
    2. execve("/system/bin/cat", ["cat", "maps"], [/* 24 vars */]) = 0
    3. mprotect(0x401db000, 4096, PROT_READ) = 0
    4. set_tid_address(0x401dced0) = 10588
    5. set_tls(0x401dd10c, 0x401dd10c, 0x401dd10c, 0x401dcedc, 0x401dcec8) = 0
    6. mmap2(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40027000
    7. madvise(0x40027000, 8192, MADV_MERGEABLE) = -1 EINVAL (Invalid argument)
    8. sigaltstack({ss_sp=0x40027000, ss_flags=0, ss_size=8192}, NULL) = 0
    9. sigaction(SIGABRT, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    10. sigaction(SIGBUS, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    11. sigaction(SIGFPE, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    12. sigaction(SIGILL, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    13. sigaction(SIGPIPE, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    14. sigaction(SIGSEGV, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    15. sigaction(SIGSTKFLT, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    16. sigaction(SIGTRAP, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    17. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x4009e000
    18. prctl(0x53564d41 /* PR_??? */, 0, 0x4009e000, 0x1000, 0x401d87ca) = -1 EINVAL (Invalid argument)
    19. openat(AT_FDCWD, "/vendor/lib/libsigchain.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    20. openat(AT_FDCWD, "/system/lib/libsigchain.so", O_RDONLY) = 3
    21. fstat64(3, {st_mode=S_IFREG|0644, st_size=5352, ...}) = 0
    22. read(3, "177ELF1113(1004"..., 52) = 52
    23. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40100000
    24. mmap2(NULL, 12288, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x401de000
    25. mmap2(0x401de000, 2953, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x401de000
    26. mmap2(0x401df000, 4100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x401df000
    27. openat(AT_FDCWD, "/vendor/lib/libc.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    28. openat(AT_FDCWD, "/system/lib/libc.so", O_RDONLY) = 4
    29. fstat64(4, {st_mode=S_IFREG|0644, st_size=608820, ...}) = 0
    30. read(4, "177ELF1113(1004"..., 52) = 52
    31. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 4, 0) = 0x40067000
    32. mmap2(NULL, 483328, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40143000
    33. mmap2(0x40143000, 414868, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4, 0) = 0x40143000
    34. mmap2(0x401aa000, 21808, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x66000) = 0x401aa000
    35. mmap2(0x401b0000, 36864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x401b0000
    36. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x40101000
    37. prctl(0x53564d41 /* PR_??? */, 0, 0x40101000, 0x1000, 0x401d87ca) = -1 EINVAL (Invalid argument)
    38. mprotect(0x401aa000, 12288, PROT_READ) = 0
    39. munmap(0x40067000, 4096) = 0
    40. close(4) = 0
    41. openat(AT_FDCWD, "/vendor/lib/liblog.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    42. openat(AT_FDCWD, "/system/lib/liblog.so", O_RDONLY) = 4
    43. fstat64(4, {st_mode=S_IFREG|0644, st_size=21744, ...}) = 0
    44. read(4, "177ELF1113(1004"..., 52) = 52
    45. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 4, 0) = 0x40042000
    46. mmap2(NULL, 28672, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4006d000
    47. mmap2(0x4006d000, 16860, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 4, 0) = 0x4006d000
    48. mmap2(0x40072000, 4108, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 4, 0x4000) = 0x40072000
    49. openat(AT_FDCWD, "/vendor/lib/libm.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    50. openat(AT_FDCWD, "/system/lib/libm.so", O_RDONLY) = 5
    51. fstat64(5, {st_mode=S_IFREG|0644, st_size=95508, ...}) = 0
    52. read(5, "177ELF1113(1004"..., 52) = 52
    53. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 5, 0) = 0x40074000
    54. mmap2(NULL, 102400, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40122000
    55. mmap2(0x40122000, 90404, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 5, 0) = 0x40122000
    56. mmap2(0x40139000, 4204, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 5, 0x16000) = 0x40139000
    57. mprotect(0x40139000, 4096, PROT_READ) = 0
    58. munmap(0x40074000, 4096) = 0
    59. close(5) = 0
    60. openat(AT_FDCWD, "/vendor/lib/libstdc++.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    61. openat(AT_FDCWD, "/system/lib/libstdc++.so", O_RDONLY) = 5
    62. fstat64(5, {st_mode=S_IFREG|0644, st_size=9396, ...}) = 0
    63. read(5, "177ELF1113(1004"..., 52) = 52
    64. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 5, 0) = 0x40021000
    65. mmap2(NULL, 16384, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40074000
    66. mmap2(0x40074000, 5782, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 5, 0) = 0x40074000
    67. mmap2(0x40076000, 4100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 5, 0x1000) = 0x40076000
    68. mprotect(0x40076000, 4096, PROT_READ) = 0
    69. munmap(0x40021000, 4096) = 0
    70. close(5) = 0
    71. mprotect(0x40072000, 4096, PROT_READ) = 0
    72. munmap(0x40042000, 4096) = 0
    73. close(4) = 0
    74. mprotect(0x401df000, 4096, PROT_READ) = 0
    75. munmap(0x40100000, 4096) = 0
    76. close(3) = 0
    77. openat(AT_FDCWD, "/vendor/lib/libcrypto.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    78. openat(AT_FDCWD, "/system/lib/libcrypto.so", O_RDONLY) = 3
    79. fstat64(3, {st_mode=S_IFREG|0644, st_size=1052960, ...}) = 0
    80. read(3, "177ELF1113(1004"..., 52) = 52
    81. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x4003a000
    82. mmap2(NULL, 1064960, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x401e1000
    83. mmap2(0x401e1000, 966164, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x401e1000
    84. mmap2(0x402ce000, 84864, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xec000) = 0x402ce000
    85. mmap2(0x402e3000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x402e3000
    86. mprotect(0x402ce000, 61440, PROT_READ) = 0
    87. munmap(0x4003a000, 4096) = 0
    88. close(3) = 0
    89. openat(AT_FDCWD, "/vendor/lib/libcutils.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    90. openat(AT_FDCWD, "/system/lib/libcutils.so", O_RDONLY) = 3
    91. fstat64(3, {st_mode=S_IFREG|0644, st_size=46480, ...}) = 0
    92. read(3, "177ELF1113(1004"..., 52) = 52
    93. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40098000
    94. mmap2(NULL, 53248, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40102000
    95. mmap2(0x40102000, 42896, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x40102000
    96. mmap2(0x4010d000, 4160, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xa000) = 0x4010d000
    97. mprotect(0x4010d000, 4096, PROT_READ) = 0
    98. munmap(0x40098000, 4096) = 0
    99. close(3) = 0
    100. openat(AT_FDCWD, "/vendor/lib/libselinux.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    101. openat(AT_FDCWD, "/system/lib/libselinux.so", O_RDONLY) = 3
    102. fstat64(3, {st_mode=S_IFREG|0644, st_size=50564, ...}) = 0
    103. read(3, "177ELF1113(1004"..., 52) = 52
    104. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x400dc000
    105. mmap2(NULL, 57344, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x402e5000
    106. mmap2(0x402e5000, 47462, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x402e5000
    107. mmap2(0x402f1000, 4144, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0xb000) = 0x402f1000
    108. mprotect(0x402f1000, 4096, PROT_READ) = 0
    109. munmap(0x400dc000, 4096) = 0
    110. close(3) = 0
    111. mprotect(0x400dd000, 4096, PROT_READ) = 0
    112. openat(AT_FDCWD, "/dev/__properties__", O_RDONLY|O_NOFOLLOW) = 3--------------->打开文件
    113. fcntl64(3, F_SETFD, FD_CLOEXEC) = 0
    114. fstat64(3, {st_mode=S_IFREG|0444, st_size=131072, ...}) = 0
    115. mmap2(NULL, 131072, PROT_READ, MAP_SHARED, 3, 0) = 0x402f3000
    116. close(3) = 0
    117. futex(0x401af5a8, FUTEX_WAKE_PRIVATE, 2147483647) = 0
    118. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    119. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    120. openat(AT_FDCWD, "/vendor/lib/libnetd_client.so", O_RDONLY) = -1 ENOENT (No such file or directory)
    121. openat(AT_FDCWD, "/system/lib/libnetd_client.so", O_RDONLY) = 3
    122. fstat64(3, {st_mode=S_IFREG|0644, st_size=9428, ...}) = 0
    123. read(3, "177ELF1113(1004"..., 52) = 52
    124. mmap2(NULL, 4096, PROT_READ, MAP_PRIVATE, 3, 0) = 0x400dc000
    125. mmap2(NULL, 16384, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4010f000
    126. mmap2(0x4010f000, 3856, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x4010f000
    127. mmap2(0x40111000, 4100, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x1000) = 0x40111000
    128. mprotect(0x40111000, 4096, PROT_READ) = 0
    129. munmap(0x400dc000, 4096) = 0
    130. close(3) = 0
    131. mprotect(0x4009e000, 4096, PROT_READ) = 0
    132. mprotect(0x40101000, 4096, PROT_READ) = 0
    133. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, 0, 0) = 0x40046000
    134. prctl(0x53564d41 /* PR_??? */, 0, 0x40046000, 0x1000, 0x401d87ca) = -1 EINVAL (Invalid argument)
    135. futex(0x401b0dd4, FUTEX_WAKE_PRIVATE, 2147483647) = 0
    136. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    137. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    138. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    139. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    140. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    141. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    142. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    143. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    144. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    145. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    146. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    147. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    148. brk(0) = 0x41525000
    149. mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40313000
    150. madvise(0x40313000, 1048576, MADV_MERGEABLE) = -1 EINVAL (Invalid argument)
    151. prctl(0x53564d41 /* PR_??? */, 0, 0x40313000, 0x100000, 0x401a1685) = -1 EINVAL (Invalid argument)
    152. munmap(0x40313000, 1048576) = 0
    153. mmap2(NULL, 2093056, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40313000
    154. prctl(0x53564d41 /* PR_??? */, 0, 0x40313000, 0x1ff000, 0x401a1685) = -1 EINVAL (Invalid argument)
    155. munmap(0x40313000, 970752) = 0
    156. munmap(0x40500000, 73728) = 0
    157. mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40100000
    158. mprotect(0x40100000, 4096, PROT_READ) = 0
    159. openat(AT_FDCWD, "/proc/stat", O_RDONLY) = 3 ----------------------->打开文件
    160. fstat64(3, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
    161. mmap2(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40500000
    162. prctl(0x53564d41 /* PR_??? */, 0, 0x40500000, 0x100000, 0x401a1685) = -1 EINVAL (Invalid argument)
    163. mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
    164. mprotect(0x40100000, 4096, PROT_READ) = 0
    165. read(3, "cpu 5457 1230 13251 421214 1598"..., 1024) = 1024
    166. read(3, " 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"..., 1024) = 212
    167. read(3, "", 1024) = 0
    168. close(3) = 0
    169. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    170. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    171. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    172. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    173. 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
    174. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    175. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    176. 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
    177. sigaction(SIGILL, {0x402a3b6d, ~[ILL TRAP BUS FPE SEGV], 0}, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}) = 0
    178. 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
    179. --- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPC, si_addr=0x40223908} ---
    180. 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
    181. sigaction(SIGILL, {0x401cea25, [], SA_RESTART|SA_SIGINFO|SA_ONSTACK}, NULL) = 0
    182. 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
    183. mprotect(0x4009e000, 4096, PROT_READ|PROT_WRITE) = 0
    184. mprotect(0x40101000, 4096, PROT_READ|PROT_WRITE) = 0
    185. mprotect(0x4009e000, 4096, PROT_READ) = 0
    186. mprotect(0x40101000, 4096, PROT_READ) = 0
    187. mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
    188. mprotect(0x40100000, 4096, PROT_READ) = 0
    189.  
    190.  openat(AT_FDCWD, "maps", O_RDONLY) = 3 ----------->打开maps文件
    191. ------------------------------------------------------------------------------------------------------------------------>这一块都是输出了
    192.  
    193.  fstat64(1, {st_mode=S_IFCHR|0666, st_rdev=makedev(204, 64), ...}) = 0
    194. read(3, "00008000-00049000 r-xp 00000000 "..., 4096) = 570
    195. write(1, "00008000-00049000 r-xp 00000000 "..., 57000008000-00049000 r-xp 00000000 00:01 1422 /init
    196. 0004a000-0004c000 r--p 00041000 00:01 1422 /init
    197. 0004c000-0004f000 rw-p 00043000 00:01 1422 /init
    198. 0004f000-00052000 rw-p 00000000 00:00 0 [heap]
    199. 40017000-40019000 rw-p 00000000 00:00 0
    200. 40072000-40073000 r--p 00000000 00:00 0
    201. 40090000-400b0000 rw-s 00000000 00:0c 2056 /dev/__properties__
    202. 400b2000-400b3000 rw-p 00000000 00:00 0
    203. 40100000-40301000 rw-p 00000000 00:00 0
    204. becd2000-becf3000 rw-p 00000000 00:00 0 [stack]
    205. ffff0000-ffff1000 r-xp 00000000 00:00 0 [vectors]
    206. ) = 570
    207. read(3, "", 4096) = 0
    208. close(3) = 0
    209. close(1) = 0
    210. mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
    211. mprotect(0x40100000, 4096, PROT_READ) = 0
    212. close(0) = 0
    213. close(2) = 0
    214. futex(0x401af5a0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
    215. mprotect(0x40100000, 4096, PROT_READ|PROT_WRITE) = 0
    216. mprotect(0x40100000, 4096, PROT_READ) = 0
    217. munmap(0x40100000, 4096) = 0
    218. exit_group(0) = ?
    219. +++ exited with 0 +++


    跟踪源码,先看一下maps_open

    1. static int maps_open(struct inode *inode, struct file *file)
    2. {
    3. return do_maps_open(inode, file, &proc_pid_maps_op); ----------->填充了proc_pid_maps_op的操作,序列文件的op
    4. }
    1. static const struct seq_operations proc_pid_maps_op = {
    2. .start = m_start,
    3. .next = m_next,
    4. .stop = m_stop,
    5. .show = show_map
    6. };
    1. static int do_maps_open(struct inode *inode, struct file *file,
    2. const struct seq_operations *ops)
    3. {
    4. struct proc_maps_private *priv;
    5. int ret = -ENOMEM;
    6. priv = kzalloc(sizeof(*priv), GFP_KERNEL);--------->分配memory?
    7. if (priv) {
    8. priv->pid = proc_pid(inode);-------->通过inode获取pid信息
    9. ret = seq_open(file, ops);------------->打开序列文件
    10. if (!ret) {
    11. struct seq_file *m = file->private_data;
    12. m->private = priv;
    13. } else {
    14. kfree(priv);
    15. }
    16. }
    17. return ret;
    18. }

    proc_maps_private 为何物?

    1. struct proc_maps_private {
    2. struct pid *pid;-------------------->仅仅一个pid并不简单,不能跟太深,会迷失...
    3. struct task_struct *task;--------->进程相关的信息
    4. #ifdef CONFIG_MMU
    5. struct vm_area_struct *tail_vma;
    6. #endif
    7. };
    1. static inline struct pid *proc_pid(struct inode *inode)
    2. {
    3. return PROC_I(inode)->pid;------------->根据inode可以找到对应的进程id
    4. }
    1. static inline struct proc_inode *PROC_I(const struct inode *inode)
    2. {
    3. return container_of(inode, struct proc_inode, vfs_inode);
    4. }


    通过inode 进而找到proc_inode,然后再找到pid

    1. struct proc_inode {
    2. struct pid *pid;--------------------->找到了....
    3. int fd;
    4. union proc_op op;
    5. struct proc_dir_entry *pde;
    6. struct ctl_table_header *sysctl;
    7. struct ctl_table *sysctl_entry;
    8. void *ns;
    9. const struct proc_ns_operations *ns_ops;
    10. struct inode vfs_inode;------------------->知道地之后,计算偏移,就可以找到pid了
    11. };

    序列文件?

    1. int seq_open(struct file *file, const struct seq_operations *op)
    2. {
    3. struct seq_file *p = file->private_data; ---------->难道数据存储在file的private_data,什么时候第一次生成的呢?理论上该是在进程创建的时候。
    4.  
    5. if (!p) {
    6. p = kmalloc(sizeof(*p), GFP_KERNEL);---------》如果为空,那么就分配一个,并将地址存放到file的似有空间里面。
    7. if (!p)
    8. return -ENOMEM;
    9. file->private_data = p;
    10. }
    11. memset(p, 0, sizeof(*p));
    12. mutex_init(&p->lock);
    13. p->op = op;----------------------------->填充之前传进来的proc_pid_maps_op, 即使是空的,也就是至少准备了一个seq_file
    14.  
    15. /*
    16. * Wrappers around seq_open(e.g. swaps_open) need to be
    17. * aware of this. If they set f_version themselves, they
    18. * should call seq_open first and then set f_version.
    19. */
    20. file->f_version = 0;
    21.  
    22. /*
    23. * seq_files support lseek() and pread(). They do not implement
    24. * write() at all, but we clear FMODE_PWRITE here for historical
    25. * reasons.
    26. *
    27. * If a client of seq_files a) implements file.write() and b) wishes to
    28. * support pwrite() then that client will need to implement its own
    29. * file.open() which calls seq_open() and then sets FMODE_PWRITE.
    30. */
    31. file->f_mode &= ~FMODE_PWRITE;
    32. return 0;
    33. }


    看一下seq_file到底是什么样子?

    1. struct seq_file {
    2. char *buf;
    3. size_t size;
    4. size_t from;
    5. size_t count;
    6. loff_t index;
    7. loff_t read_pos;
    8. u64 version;
    9. struct mutex lock;
    10. const struct seq_operations *op;
    11. void *private;
    12. };


    感觉就是一段buffer,然后增加了版本,代写哦啊,偏移位置,锁以及ops等信息

    那么接下来应该是读取了?因为理论上应该是先open,然后读取的

    1. ssize_t seq_read(struct file *file, char __user *buf, size_t size, loff_t *ppos)
    2. {
    3. struct seq_file *m = file->private_data; -------------->不知道这个数据是不是空的啊?现在应该不是空的了,上面已经填充了...
    4. size_t copied = 0;
    5. loff_t pos;
    6. size_t n;
    7. void *p;
    8. int err = 0;
    9.  
    10. mutex_lock(&m->lock);
    11.  
    12. /* Don't assume *ppos is where we left it */
    13. if (unlikely(*ppos != m->read_pos)) {
    14. m->read_pos = *ppos;
    15. while ((err = traverse(m, *ppos)) == -EAGAIN) ---------------->1. 做什么?
    16. ;
    17. if (err) {
    18. /* With prejudice... */
    19. m->read_pos = 0;
    20. m->version = 0;
    21. m->index = 0;
    22. m->count = 0;
    23. goto Done;
    24. }
    25. }
    26.  
    27. /*
    28. * seq_file->op->..m_start/m_stop/m_next may do special actions
    29. * or optimisations based on the file->f_version, so we want to
    30. * pass the file->f_version to those methods.
    31. *
    32. * seq_file->version is just copy of f_version, and seq_file
    33. * methods can treat it simply as file version.
    34. * It is copied in first and copied out after all operations.
    35. * It is convenient to have it as part of structure to avoid the
    36. * need of passing another argument to all the seq_file methods.
    37. */
    38. m->version = file->f_version;
    39. /* grab buffer if we didn't have one */
    40. if (!m->buf) {
    41. m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
    42. if (!m->buf)
    43. goto Enomem;
    44. }
    45. /* if not empty - flush it first */
    46. if (m->count) {
    47. n = min(m->count, size);
    48. err = copy_to_user(buf, m->buf + m->from, n);
    49. if (err)
    50. goto Efault;
    51. m->count -= n;
    52. m->from += n;
    53. size -= n;
    54. buf += n;
    55. copied += n;
    56. if (!m->count)
    57. m->index++;
    58. if (!size)
    59. goto Done;
    60. }
    61. /* we need at least one record in buffer */
    62. pos = m->index;
    63. p = m->op->start(m, &pos);
    64. while (1) {
    65. err = PTR_ERR(p);
    66. if (!p || IS_ERR(p))
    67. break;
    68. err = m->op->show(m, p); ------------->显示?
    69. if (err < 0)
    70. break;
    71. if (unlikely(err))
    72. m->count = 0;
    73. if (unlikely(!m->count)) {
    74. p = m->op->next(m, p, &pos);
    75. m->index = pos;
    76. continue;
    77. }
    78. if (m->count < m->size)
    79. goto Fill;
    80. m->op->stop(m, p);
    81. kfree(m->buf);
    82. m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
    83. if (!m->buf)
    84. goto Enomem;
    85. m->count = 0;
    86. m->version = 0;
    87. pos = m->index;
    88. p = m->op->start(m, &pos);
    89. }
    90. m->op->stop(m, p);
    91. m->count = 0;
    92. goto Done;
    93. Fill:
    94. /* they want more? let's try to get some more */
    95. while (m->count < size) {
    96. size_t offs = m->count;
    97. loff_t next = pos;
    98. p = m->op->next(m, p, &next);
    99. if (!p || IS_ERR(p)) {
    100. err = PTR_ERR(p);
    101. break;
    102. }
    103. err = m->op->show(m, p);
    104. if (m->count == m->size || err) {
    105. m->count = offs;
    106. if (likely(err <= 0))
    107. break;
    108. }
    109. pos = next;
    110. }
    111. m->op->stop(m, p);
    112. n = min(m->count, size);
    113. err = copy_to_user(buf, m->buf, n);
    114. if (err)
    115. goto Efault;
    116. copied += n;
    117. m->count -= n;
    118. if (m->count)
    119. m->from = n;
    120. else
    121. pos++;
    122. m->index = pos;
    123. Done:
    124. if (!copied)
    125. copied = err;
    126. else {
    127. *ppos += copied;
    128. m->read_pos += copied;
    129. }
    130. file->f_version = m->version;
    131. mutex_unlock(&m->lock);
    132. return copied;
    133. Enomem:
    134. err = -ENOMEM;
    135. goto Done;
    136. Efault:
    137. err = -EFAULT;
    138. goto Done;
    139. }
    140. EXPORT_SYMBOL(seq_read);


    traverse 做了什么呢?

    1. static int traverse(struct seq_file *m, loff_t offset)
    2. {
    3. loff_t pos = 0, index;
    4. int error = 0;
    5. void *p;
    6.  
    7. m->version = 0;
    8. index = 0;
    9. m->count = m->from = 0;
    10. if (!offset) {
    11. m->index = index;
    12. return 0;
    13. }
    14. if (!m->buf) { ---------------->这个都不知道是不是空的?
    15. m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL);
    16. if (!m->buf)
    17. return -ENOMEM;
    18. }
    19. p = m->op->start(m, &index);-----------调用m_start,是准备什么吗?
    20. while (p) {
    21. error = PTR_ERR(p);
    22. if (IS_ERR(p))
    23. break;
    24. error = m->op->show(m, p);
    25. if (error < 0)
    26. break;
    27. if (unlikely(error)) {
    28. error = 0;
    29. m->count = 0;
    30. }
    31. if (m->count == m->size)
    32. goto Eoverflow;
    33. if (pos + m->count > offset) {
    34. m->from = offset - pos;
    35. m->count -= m->from;
    36. m->index = index;
    37. break;
    38. }
    39. pos += m->count;
    40. m->count = 0;
    41. if (pos == offset) {
    42. index++;
    43. m->index = index;
    44. break;
    45. }
    46. p = m->op->next(m, p, &index);
    47. }
    48. m->op->stop(m, p);
    49. m->index = index;
    50. return error;
    51.  
    52. Eoverflow:
    53. m->op->stop(m, p);
    54. kfree(m->buf);
    55. m->buf = kmalloc(m->size <<= 1, GFP_KERNEL);
    56. return !m->buf ? -ENOMEM : -EAGAIN;
    57. }


    m_start 做了什么?

    1. static void *m_start(struct seq_file *m, loff_t *pos)
    2. {
    3. struct proc_maps_private *priv = m->private;
    4. unsigned long last_addr = m->version;
    5. struct mm_struct *mm;
    6. struct vm_area_struct *vma, *tail_vma = NULL;
    7. loff_t l = *pos;
    8.  
    9. /* Clear the per syscall fields in priv */
    10. priv->task = NULL;
    11. priv->tail_vma = NULL;
    12.  
    13. /*
    14. * We remember last_addr rather than next_addr to hit with
    15. * mmap_cache most of the time. We have zero last_addr at
    16. * the beginning and also after lseek. We will have -1 last_addr
    17. * after the end of the vmas.
    18. */
    19.  
    20. if (last_addr == -1UL)
    21. return NULL;
    22.  
    23. priv->task = get_pid_task(priv->pid, PIDTYPE_PID); ---------->通过pid 获取到task_struct
    24. if (!priv->task)
    25. return ERR_PTR(-ESRCH);
    26.  
    27. mm = mm_for_maps(priv->task);------------->这个看着很关键。。。,其实就是进行了权限检测,并得到了mm指针
    28. if (!mm || IS_ERR(mm))
    29. return mm;
    30. down_read(&mm->mmap_sem);
    31.  
    32. tail_vma = get_gate_vma(priv->task->mm); ---------->获取vma的结束位置
    33.  priv->tail_vma = tail_vma;
    34.  
    35. /* Start with last addr hint */
    36. vma = find_vma(mm, last_addr);-------------->从红黑树中得到对应的虚拟地址区域
    37. if (last_addr && vma) {
    38. vma = vma->vm_next;
    39. goto out;
    40. }
    41.  
    42. /*
    43. * Check the vma index is within the range and do
    44. * sequential scan until m_index.
    45. */
    46. vma = NULL;
    47. if ((unsigned long)l < mm->map_count) {
    48. vma = mm->mmap;
    49. while (l-- && vma)
    50. vma = vma->vm_next;
    51. goto out;
    52. }
    53.  
    54. if (l != mm->map_count)
    55. tail_vma = NULL; /* After gate vma */
    56.  
    57. out:
    58. if (vma)
    59. return vma;
    60.  
    61. /* End of vmas has been reached */
    62. m->version = (tail_vma != NULL)? 0: -1UL;
    63. up_read(&mm->mmap_sem);
    64. mmput(mm); -------------->释放对mm的使用记录
    65. return tail_vma;
    66. }



    1. struct mm_struct *mm_for_maps(struct task_struct *task)
    2. {
    3. return mm_access(task, PTRACE_MODE_READ);------------>看着像是ptrace实现的额?
    4. }
    1. static struct mm_struct *mm_access(struct task_struct *task, unsigned int mode)
    2. {
    3. struct mm_struct *mm;
    4. int err;
    5.  
    6. err = mutex_lock_killable(&task->signal->cred_guard_mutex);
    7. if (err)
    8. return ERR_PTR(err);
    9.  
    10. mm = get_task_mm(task); -------------->通过task_struct 获取mm_struct结构,并且增加对mm_struct 使用的计数
    11. if (mm && mm != current->mm &&
    12. !ptrace_may_access(task, mode) && --------------->对进程进行跟踪,这里会进行严格的权限检测
    13. !capable(CAP_SYS_RESOURCE)) {
    14. mmput(mm);
    15. mm = ERR_PTR(-EACCES);
    16. }
    17. mutex_unlock(&task->signal->cred_guard_mutex);
    18.  
    19. return mm;
    20. }


    总结m_start 所做的事情,也就是说traverse找到了对应的vm_area_struct

    pid-->task_struct->mm_struct->vm_area_struct

    接下来就要调用show_map

    1. static int show_map(struct seq_file *m, void *v)
    2. {
    3. struct vm_area_struct *vma = v;
    4. struct proc_maps_private *priv = m->private;
    5. struct task_struct *task = priv->task;
    6.  
    7. show_map_vma(m, vma);-------->显示vma 区域
    8.  
    9. if (m->count < m->size) /* vma is copied successfully */
    10. m->version = (vma != get_gate_vma(task->mm))
    11. ? vma->vm_start : 0;
    12. return 0;
    13. }
    1. static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
    2. {
    3. struct mm_struct *mm = vma->vm_mm;
    4. struct file *file = vma->vm_file;
    5. vm_flags_t flags = vma->vm_flags;
    6. unsigned long ino = 0;
    7. unsigned long long pgoff = 0;
    8. unsigned long start, end;
    9. dev_t dev = 0;
    10. int len;
    11.  
    12. if (file) {
    13. struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
    14. dev = inode->i_sb->s_dev;
    15. ino = inode->i_ino;
    16. pgoff = ((loff_t)vma->vm_pgoff) << PAGE_SHIFT;
    17. }
    18.  
    19. /* We don't show the stack guard page in /proc/maps */
    20. start = vma->vm_start;
    21. if (stack_guard_page_start(vma, start)) -------->可以查看到该区域的增长是向下,还是向上的...
    22. start += PAGE_SIZE;
    23. end = vma->vm_end;
    24. if (stack_guard_page_end(vma, end))
    25. end -= PAGE_SIZE;
    26.  
    27. seq_printf(m, "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
    28. start,
    29. end,
    30. flags & VM_READ ? 'r' : '-',
    31. flags & VM_WRITE ? 'w' : '-',
    32. flags & VM_EXEC ? 'x' : '-',
    33. flags & VM_MAYSHARE ? 's' : 'p',
    34. pgoff,
    35. MAJOR(dev), MINOR(dev), ino, &len);------------>关键的一句输出
    36.  
    37.  
    38.  /*
    39. * Print the dentry name for named mappings, and a
    40. * special [heap] marker for the heap:
    41. */
    42. if (file) {
    43. pad_len_spaces(m, len);
    44. seq_path(m, &file->f_path, " ");
    45. } else {
    46. const char *name = arch_vma_name(vma);
    47. if (!name) {
    48. if (mm) {
    49. if (vma->vm_start <= mm->brk &&
    50. vma->vm_end >= mm->start_brk) { ------------>堆的区域
    51. name = "[heap]";
    52. } else if (vma->vm_start <= mm->start_stack &&
    53. vma->vm_end >= mm->start_stack) {------------->栈的区域
    54. name = "[stack]";
    55. }
    56. } else {
    57. name = "[vdso]";
    58. }
    59. }
    60. if (name) {
    61. pad_len_spaces(m, len);
    62. seq_puts(m, name);
    63. }
    64. }
    65. seq_putc(m, ' ');
    66. }



    详细看一下mm_struct的几个成员:

    1. unsigned long total_vm, locked_vm, shared_vm, exec_vm;
    2. unsigned long stack_vm, reserved_vm, def_flags, nr_ptes;
    3. unsigned long start_code, end_code, start_data, end_data;
    4. unsigned long start_brk, brk, start_stack;
    5. unsigned long arg_start, arg_end, env_start, env_end;
    6.  
    7. unsigned long saved_auxv[AT_VECTOR_SIZE]; /* for /proc/PID/auxv */
    8.  
    9. /*
    10. * Special counters, in some configurations protected by the
    11. * page_table_lock, in other configurations by being atomic.
    12. */
    13. struct mm_rss_stat rss_stat;



    图片源自http://blog.csdn.net/dyllove98/article/details/8917197

    参考:http://blog.csdn.net/dyllove98/article/details/8917197

    【作者】张昺华
    【大饼教你学系列】https://edu.csdn.net/course/detail/10393
    【新浪微博】 张昺华--sky
    【twitter】 @sky2030_
    【微信公众号】 张昺华
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利.
  • 相关阅读:
    TMainMenu 类 手动建立菜单 : 指定快捷键《转》
    确定多重选择列表控件 (List Control) 中的选定内容
    【320K】大峡谷The Music of The Grand Canyon
    35种音乐的分类
    ASP中常用的变量命名规则
    关于DBF文件导入问题
    ASP.NET里的变量命名规则
    ASP中数据库安全问题之我见
    用err.raise自定义错误信息
    关于编程风格的讨论 PioneerMan(原作)
  • 原文地址:https://www.cnblogs.com/sky-heaven/p/13686390.html
Copyright © 2020-2023  润新知