7.1、进程简介
Linux是一个多用户多任务的操作系统,可以同时执行几个任务,并在一个任务还没有执行完成就执行另一项任务。在Linux中,每个执行的任务都称为进程(process)。通常进程与程序的区别为:
程序 (program):通常为binary program,放置在储存媒体中 (如硬盘、光盘、软盘、磁带等),为实体文件的型态存在。 进程 (process): 程序被触发后, 运行者的权限与属性、 程序的程序码与所需数据等都会被加载内存中,操作系统并给予这个内存内的单元一个识别码 (PID),可以说,程序就是一个正在运行中的程序。 |
Linux系统除了初始化进程init以外,其他进程都是通过fork()和clone()函数创建的。调用fork()和clone()函数的是父进程。Linux中个进程是相互联系的,所有进程都是衍生自进程号为1的init进程,由此就形成了一颗以init为根的进程树,每个进程都是该树中的一个节点。
[root@mylinux ~]# pstree #查看系统的进程树 init─┬─acpid ├─agetty ├─atd ├─auditd───{auditd} ├─barad_agent─┬─barad_agent │ └─barad_agent───2*[{barad_agent}] ├─crond ├─dbus-daemon ├─hald─┬─hald-runner─┬─hald-addon-acpi │ │ └─hald-addon-inpu │ └─{hald} ├─master─┬─pickup │ └─qmgr ├─6*[mingetty] ├─mysqld_safe───mysqld───9*[{mysqld}] ├─rpc.statd ├─rpcbind ├─rsyslogd───3*[{rsyslogd}] ├─sap1002 ├─sap1005 ├─sap1006 ├─secu-tcs-agent───sap1004 ├─sgagent───{sgagent} ├─sshd───sshd───bash───pstree ├─udevd───2*[udevd] └─watchdog.sh───sleep
7.2、进程的管理
查看进程ps
ps [选项]
常用选项: a: 所有与终端有关的进程 u: 进程详细信息 x: 所有与终端无关的进程-e:显示所有进程(等同于-A) -f:完整格式列表输出 -F:显示额外信息 -h:不显示标题 -H:显示进程层次 -l:长格式输出 -r:只显示当前终端运行的进程 -o PROPERTY1,PROPERTY2(显示指定字段) |
[root@mylinux ~]# ps -ef #以全格式显示系统中所有进程信息 UID PID PPID C STIME TTY TIME CMD root 1 0 0 Apr17 ? 00:00:01 /sbin/init root 2 0 0 Apr17 ? 00:00:00 [kthreadd] root 3 2 0 Apr17 ? 00:00:00 [migration/0] root 4 2 0 Apr17 ? 00:00:04 [ksoftirqd/0] root 5 2 0 Apr17 ? 00:00:00 [stopper/0] root 6 2 0 Apr17 ? 00:00:00 [watchdog/0] ...
字段 | 说明 | 字段 | 说明 |
UID | 运行进程的用户 | STIME | 进程启动的事件 |
PID | 进程的ID | TTY | 终端号 |
PPID | 父进程的ID | TIME | 进程使用的CPU时间 |
C | CPU调度情况 | CMD | 启动进程的命令 |
[root@mylinux ~]# ps -ef | grep bash #查看包含bash关键字的进程信息 root 10376 10372 0 18:48 pts/0 00:00:00 -bash root 16436 10376 0 20:24 pts/0 00:00:00 grep bash [root@mylinux ~]# ps -aux #查看进程资源的使用 USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.1 19356 1448 ? Ss Apr17 0:01 /sbin/ini root 2 0.0 0.0 0 0 ? S Apr17 0:00 [kthread] root 3 0.0 0.0 0 0 ? S Apr17 0:00 [migrati] root 4 0.0 0.0 0 0 ? S Apr17 0:04 [ksoftir] root 5 0.0 0.0 0 0 ? S Apr17 0:00 [stopper] root 6 0.0 0.0 0 0 ? S Apr17 0:00 [watchdo] root 7 0.0 0.0 0 0 ? S Apr17 0:34 [events/] root 8 0.0 0.0 0 0 ? S Apr17 0:00 [events/] ...
字段 | 说明 | 字段 | 说明 |
USER | 运行进程的用户 | RSS | 进程占用物理内存的大小 |
PID | 进程的ID | STAT | 进程的状态 |
%CPU | 进程的CPU占用率 | START | 进程启动的时间 |
%MEM | 进程的内存使用率 | TIME | 进程使用的CPU时间 |
VSZ | 进程占用虚拟内存的大小 | COMMAND | 启动进程的命令 |
进程状态的表示含义:
D:不可中断的睡眠 S:可中断的睡眠 R:运行或就绪 T:停止 Z:僵死 <:高优先级进程 N:低优先级进程 +:前台进程组中的进程 l: 多线程进程 s: 会话进程首进程 |
7.3、进程的优先级与通信
在linux系统中,每个进程在执行时都会赋予一个优先级(priority, PRI),等级越高,进程获得的CPU时间就越多。所以级别越高的进程,运行时间就越短。其中优先级又分为实时与静态:
实时优先级:0-99,数字越小,优先级越高 静态优先级:100-139, nice值调整,nice数值越小,优先级越高 |
PRI 值是由内核动态调整,使用者无法直接调整PRI值的。因此想要调整进程优先级需要通过调整nice值。nice值可调整的范围为-20 ~ 19;当 nice 值为负值时,那么该程序就会降低 PRI 值,提高优先级,即-20表示等级最高,19则表示最低;其中-1~-20只有root用户才能使用,进程运行的默认等级为0。
PRI(new) = PRI(old) + nice #调整后的进程优先级计算方法
[root@mylinux home]# vim test & #nice值为0 [1] 17894 [root@mylinux home]# nice vim test & #nice值为10,默认为10 [2] 17958 [root@mylinux home]# nice -19 vim test & #nice值为19 [3] 18022 [root@mylinux home]# nice --19 vim test & #nice值为-19 [4] 18023 [3]+ Stopped nice -19 vim test [root@mylinux home]# nice --20 vim test & #nice值为-20 [5] 18024 [4]+ Stopped nice --19 vim test [root@mylinux home]# ps -l #查看进程的优先级与nice值 F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 4 S 0 10376 10372 0 80 0 - 27077 wait pts/0 00:00:00 bash 0 T 0 17894 10376 0 80 0 - 34209 signal pts/0 00:00:00 vim 0 T 0 17958 10376 0 90 10 - 34209 signal pts/0 00:00:00 vim 0 T 0 18022 10376 0 99 19 - 34209 signal pts/0 00:00:00 vim 4 T 0 18023 10376 0 61 -19 - 34209 signal pts/0 00:00:00 vim 4 T 0 18024 10376 0 60 -20 - 34209 signal pts/0 00:00:00 vim 4 T 0 18184 10376 0 60 -20 - 34209 signal pts/0 00:00:00 vim 4 R 0 18212 10376 0 80 0 - 27033 - pts/0 00:00:00 ps [6]+ Stopped nice --20 vim test
作业控制JOB
在Linux系统中,启动一个进程主要有两种途径:调度启动与手工启动。调度启动将即任务计划,而手工启动就是用户输入命令或者单击图形化窗口启动一个程序。根据进程的分类,手工启动又可以分为前台启动与后台启动:
前台作业:占据了命令提示符 后台作业:启动之后,释放命令提示符,后续的操作在后台完成 |
前台作业切换到后台作业的方法:
Ctrl+z: 把正在前台的作业送往后台 COMMAND &: 让命令在后台执行 |
命令 | 功能 |
fg [[%]JOBID] | 将后台作业送到前台 |
bg [[%]JOBID] | 让后台停止的作业继续工作 |
Jobs | 查看所有后台运行的作业 |
kill %JOBID | 终止某作业 |
[root@mylinux home]# jobs #查看后台作业 [1] Stopped vim test [2] Stopped nice vim test [3] Stopped nice -19 vim test [4] Stopped nice --19 vim test [5]- Stopped nice --40 vim test # ‘-‘表示将默认操作的作业 [6]+ Stopped nice --20 vim test # ‘+‘将默认操作的第二个作业
进程间通信的方式
常见的进程间通信(IPC:Inter Process Communication)方式有:共享内存、Semaphore、信号:(Signal)。使用kill命令可以通知信号给进程,常见的信号有:
1:SIGHUP: 让一个进程不用重启,就可以重读其配置文件,并让新的配置信息生效; 2: SIGINT: Ctrl+c: 中断一个进程 9: SIGKILL:杀死一个进程 |
[root@mylinux home]# kill -l #显示所有的信号 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2 13) SIGPIPE 14) SIGALRM 15) SIGTERM 16) SIGSTKFLT 17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1 64) SIGRTMAX [root@mylinux home]# ps PID TTY TIME CMD 10376 pts/0 00:00:00 bash 17894 pts/0 00:00:00 vim 17958 pts/0 00:00:00 vim 18022 pts/0 00:00:00 vim 18023 pts/0 00:00:00 vim 18024 pts/0 00:00:00 vim 18184 pts/0 00:00:00 vim 20178 pts/0 00:00:00 ps [root@mylinux home]# kill -9 18184 #杀死PID为18184号的进程 [6]+ 已杀死 nice --20 vim test [root@mylinux home]# ps PID TTY TIME CMD 10376 pts/0 00:00:00 bash 17894 pts/0 00:00:00 vim 17958 pts/0 00:00:00 vim 18022 pts/0 00:00:00 vim 18023 pts/0 00:00:00 vim 18024 pts/0 00:00:00 vim 20179 pts/0 00:00:00 ps
pkill/pgrep [options] pattern命令
-u uid: 仅匹配有效进程
-U uid: 仅匹配真实进程
-t terminal: 与指定终端相关的进程
-l: 显示进程名
-a: 显示完整格式的进程名
-P pid: 显示其父进程为此处指定的进程的进程列表
杀死进程:kill PID killall COMMAND
7.4、系统监控相关命令top/ps/vmstat/glances/dstat
内存监控vmstat/mpstat
Linux系统的内存分为物理内存和虚拟内存两种。物理内存是真实的,也就是物理内存条上的内存;而虚拟内存则是采用硬盘空间补充物理内存,将暂时不使用的内存页写到硬盘上以腾出更多的物理内存让需要的进程使用。vmstat是linux中监控内存条的常用工具,可以对操作系统的虚拟内存、进程和CPU等整体情况进行监视。
使用格式:
vmstat [-a] [-n] [-t] [-S unit] [delay [ count]] vmstat [-s] [-n] [-S unit] vmstat [-m] [-n] [delay [ count]] vmstat [-d] [-n] [delay [ count]] vmstat [-p disk partition] [-n] [delay [ count]] vmstat [-f] vmstat [-V]
[root@mylinux ~]# vmstat 5 10 #5秒为间隔,收集10次指标 procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu----- r b swpd free buff cache si so bi bo in cs us sy id wa st 0 0 0 79000 170024 572596 0 0 1 26 21 31 0 1 99 1 0 0 0 0 78868 170024 572620 0 0 0 1825 191 272 1 1 95 3 0 0 0 0 78908 170024 572628 0 0 0 38 193 281 1 1 98 1 0 0 0 0 78924 170024 572628 0 0 0 5 159 233 1 0 99 0 0 0 0 0 78924 170024 572632 0 0 0 0 151 221 0 0 99 0 0 0 0 0 78932 170024 572632 0 0 0 6 153 227 0 0 99 0 0 0 0 0 79056 170024 572632 0 0 0 0 155 227 0 0 99 0 0 0 0 0 79056 170024 572632 0 0 0 6 165 240 0 0 99 0 0 0 0 0 79164 170024 572632 0 0 0 0 159 237 0 1 99 0 0 0 0 0 79064 170024 572632 0 0 0 13 165 237 0 0 99 0 0
输出各字段所代表的含义为:
字段 | 类别 | 说明 |
r | procs(进程) | 运行或等待 CPU 时间片的进程的个数 |
b | procs(进程) | 被阻塞(通常为等待IO 完成)的进程队列的长度 |
swpd | memory(内存) | 已经使用的交换内存(kb) |
free | memory(内存) | 未使用物理内存大小(kb) |
buff | memory(内存) | 用作缓冲区的内存数,通常与缓存写操作相关(kb) |
cache | memory(内存) | 用作高速缓存的内存数,通常与缓存读操作相关(kb) |
si | swap(交换页面) | 从磁盘交换到内存的交换页数据(kb) |
so | swap(交换页面) | 从内存交换到磁盘的交换页数据(kb) |
bi | IO(块设备) | 从块设备读入的数据量,通常是速率,kb/s |
bo | IO(块设备) | 保存至块设备中的数据量,通常是速率,kb/s |
in | system(系统) | 中断发生速率, 每秒的中断数 |
cs | system(系统) | 上下文切换,进程切换速率, 每秒钟切换的次数 |
us | CPU(处理器) | 用户进程使用的CPU时间(%) |
sy | CPU(处理器) | 系统进程使用的CPU时间(%) |
id | CPU(处理器) | CPU空闲时间(%) |
wa | CPU(处理器) | 等待IO完成所消耗的时间(%) |
st | CPU(处理器) | 从虚拟设备中获得的时间(%) |
vmstat命令只能显示CPU总的性能,对于有多个CPU的计算机,如果要查看每个CPU的性能,可以使用mpstat命令。
mpstat [-P {|ALL}] [internal [count]] -P {|ALL} 表示监控哪个CPU, cpu在[0,cpu个数-1]中取值 internal 相邻的两次采样的间隔时间、 count 采样的次数,count只能和delay一起使用 |
[root@mylinux ~]# mpstat Linux 2.6.32-642.11.1.el6.x86_64 (mylinux) 2017年04月24日 _x86_64_ (1 CPU) 09时31分05秒 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %idle 09时31分05秒 all 0.42 0.00 0.51 0.52 0.00 0.00 0.00 0.00 98.55
命令输出字段的说明:
%user 在internal时间段里,用户态的CPU时间(%),不包含nice值为负进程 (usr/total)*100 %nice 在internal时间段里,nice值为负进程的CPU时间(%) (nice/total)*100 %sys 在internal时间段里,内核时间(%) (system/total)*100 %iowait 在internal时间段里,硬盘IO等待时间(%) (iowait/total)*100 %irq 在internal时间段里,硬中断时间(%) (irq/total)*100 %soft 在internal时间段里,软中断时间(%) (softirq/total)*100 %idle 在internal时间段里,CPU除去等待磁盘IO操作外的因为任何原因而空闲的时间闲置时间(%) (idle/total)*100 |
磁盘监控iostat
iostat是I/O statistics的缩写,iostat工具可以对系统的洗盘操作活动进程监控,并汇报磁盘活动统计情况。
用法: iostat [ 选项 ] [ <时间间隔> [ <次数> ] ]
-c:只显示CPU使用情况 -d:只显示磁盘的使用情况 -k:以‘kb/秒‘代替‘块/秒‘作为统计结果的单位 -m:以‘mb/秒‘代替‘块/秒‘作为统计结果的单位 -n:显示nfs目录的统计信息 -x:显示扩展信息 -t:在每次统计的结果中显示时间 -p[device|ALL]:显示设备所有分区的统计信息 |
[root@mylinux ~]# iostat -t -d -k 5 #以kb为单位,不显示cpu数据,没我秒刷新一次 Linux 2.6.32-642.11.1.el6.x86_64 (mylinux) 2017年04月24日 _x86_64_ (1 CPU) 2017年04月24日 09时45分00秒 Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn vda 1.36 0.73 25.47 427554 14881144 vdb 0.02 0.07 0.15 41008 88578 dm-0 0.01 0.00 0.04 1694 24774 2017年04月24日 09时45分05秒 Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn vda 1.40 0.00 6.41 0 32 vdb 0.00 0.00 0.00 0 0 dm-0 0.00 0.00 0.00 0 0
命令输出字段的说明:
Device: 设备或分区名 tps: 每秒发送到设备商的IO请求数 kB_read/s:每秒钟读的数据(kb/秒) kB_wrtn/s:每秒钟写的数据(kb/秒) kB_read :设备读数据的总大小(kb) kB_wrtn :设备写数据的总大小(kb) |
监控工具dstat
dstat 是一个可以取代vmstat,iostat,netstat和ifstat这些命令的多功能产品。dstat克服了这些命令的局限并增加了一些另外的功能,增加了监控项,也变得更灵活了。dstat可以很方便监控系统运行状况并用于基准测试和排除故障。
使用格式:dstat [-afv] [options..] [delay [count]]
常用选项: -l :显示负载统计量 -m :显示内存使用率(包括used,buffer,cache,free值) -r :显示I/O统计 -s :显示交换分区使用情况 -t :将当前时间显示在第一行 –fs :显示文件系统统计数据(包括文件总数量和inodes值) –nocolor :不显示颜色(有时候有用) –socket :显示网络统计数据 –tcp :显示常用的TCP统计 –udp :显示监听的UDP接口及其当前用量的一些动态数据 --disk-util :显示某一时间磁盘的忙碌状况 --freespace :显示当前磁盘空间使用率 --proc-count :显示正在运行的程序数量 --top-bio :指出块I/O最大的进程 --top-cpu :图形化显示CPU占用最大的进程 --top-io :显示正常I/O最大的进程 --top-mem :显示占用最多内存的进程 |
综合监控工具top/htop
top是一个非常优秀的交互式性能监控工具,可以在一个同一的界面按照用户指定的时间间隔刷新显示内存、CPU、进程、用户数据等信息。
用法:top -hv | -abcHimMsS -d delay -n iterations -p pid [, pid ...]
常用选项: -d delay:指定top命令刷新时间间隔(秒) -n:只i的那个top命令再刷新n此后退出 -u usr:top命令只显示usr用户的进程信息 -p pid:top命令只显示指定的pid进程信息 |
top - 10:07:49 up 6 days, 19:13, 1 user, load average: 0.00, 0.00, 0.00 Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie Cpu(s): 0.3%us, 0.3%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0. Mem: 1020128k total, 823700k used, 196428k free, 136732k buffers Swap: 0k total, 0k used, 0k free, 497784k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1479 mysql 20 0 368m 20m 2068 S 0.3 2.0 2:14.76 mysqld 1796 root 20 0 32352 14m 476 S 0.3 1.5 28:10.83 sap1005 1 root 20 0 19356 1412 1088 S 0.0 0.1 0:01.72 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd 3 root RT 0 0 0 0 S 0.0 0.0 0:00.00 migration/0 4 root 20 0 0 0 0 S 0.0 0.0 0:04.71 ksoftirqd/0 5 root RT 0 0 0 0 S 0.0 0.0 0:00.00 stopper/0 6 root RT 0 0 0 0 S 0.0 0.0 0:00.75 watchdog/0 7 root 20 0 0 0 0 S 0.0 0.0 0:36.38 events/0 8 root 20 0 0 0 0 S 0.0 0.0 0:00.00 events/0 9 root 20 0 0 0 0 S 0.0 0.0 0:00.00 events_long/0 10 root 20 0 0 0 0 S 0.0 0.0 0:00.00 events_power_ 11 root 20 0 0 0 0 S 0.0 0.0 0:00.00 cgroup
进入监控界面后可以进行的操作:
M: 根据驻留内存大小进行排序 P:根据CPU使用百分比进行排序 T: 根据累计时间进行排序 l: 是否显示平均负载和启动时间 t: 是否显示进程和CPU状态相关信息 m: 是否显示内存相关信息 c: 是否显示完整的命令行信息 q: 退出top k: 终止某个进程 s: 改变top刷新时间间隔 -d: 指定延迟时长,单位是秒 -b: 批次显示 -n #:在批模式下,共显示多少批 |
各字段所代表的含义:
top - 10:07:49 up 6 days, 19:13, 1 user, load average: 0.00, 0.00, 0.00
当前时间为10:07:49,已经运行了6天,有一个用户在登录,最近1分钟、5分钟、15分钟的平均负载都为为0.00。 |
Tasks: 95 total, 1 running, 94 sleeping, 0 stopped, 0 zombie
total:系统当前的进程总数 running,正在运行的进程数 sleeping,正在休眠的进程数 stopped,停止的进程数 zombie,僵尸进程数 |
Cpu(s): 0.3%us, 0.3%sy, 0.0%ni, 99.3%id, 0.0%wa, 0.0%hi, 0.0%si, 0.
us:用户进程使用的CPU时间(%) sy:系统进程使用的CPU时间(%) ni:改变过优先级的用户进程占用的CPU百分比 id:CPU空闲时间(%) wa:等待IO完成所消耗的时间(%) hi:硬件中断占用的CPU百分比 si:软件中断占用的CPU百分比 st:虚拟设备的CPU百分比 |
Mem: 1020128k total, 823700k used, 196428k free, 136732k buffers
total:物理内存总量 used:已经使用的物理内存数量 free:空闲物理内存数量 buffers:用作缓冲区的内存数量 |
Swap: 0k total, 0k used, 0k free, 497784k cached
total:虚拟内存总量 used:已经使用的虚拟内存数量 free:空闲虚拟内存数量 buffers:用作缓存的虚拟内存数量 |
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 1479 mysql 20 0 368m 20m 2068 S 0.3 2.0 2:14.76 mysqld 1796 root 20 0 32352 14m 476 S 0.3 1.5 28:10.83 sap1005 1 root 20 0 19356 1412 1088 S 0.0 0.1 0:01.72 init 2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
PID:进程ID USER:进程运行者 PR:优先级 NI:nice值,-20最高,19最低 VIRT:进程使用的虚拟内存大小 RES:进程使用的物理内存大小 SHR:共享内存大小 S: 进程状态 %CPU:进程占用CPU的百分比 %MEM:警察呢个使用的物理内存百分比 TIME+:进程使用总的CPU时间 COMMAND:进程名称 |
htop与传统的 top 命令功能一样,但它有更加强大的功能及能显示更多的信息。它类似于 top 命令,但可以让你在垂直和水平方向上滚动,所以你可以看到系统上运行的所有进程,以及他们完整的命令行。可以不用输入进程的 PID 就可以对此进程进行相关的操作 (killing, renicing)。
用法:htop [-dChusv]
常用选项: u: 选择指定用户的进程 l: 显示进程所打开的文件列表 s: 显示进程执行的系统调用 a: 绑定进程到指定的CPU上 #:快速将光标定位至指定的PID进程上 |
其显示界面为如下,其详细用法在帮助中有具体说明。
本文出自 “随风而飘” 博客,请务必保留此出处http://yinsuifeng.blog.51cto.com/10173491/1918731
原文地址:http://yinsuifeng.blog.51cto.com/10173491/1918731