✏️ update
This commit is contained in:
parent
370cd588bc
commit
b0367180db
@ -1,6 +1,6 @@
|
||||
## 什么是 CPU 上下文
|
||||
|
||||
Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉。而在每个任务运行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器(Program Counter,PC)。
|
||||
Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们,造成多任务同时运行的错觉。而在每个任务运行前,CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器(Program Counter,PC)。
|
||||
|
||||
CPU 寄存器,是 CPU 内置的容量小、但速度极快的内存。而程序计数器,则是用来存储 CPU 正在执行的指令位置、或者即将执行的下一条指令位置。它们都是 CPU 在运行任何任务前,必须的依赖环境,因此也被叫做 CPU 上下文。
|
||||
|
||||
@ -10,7 +10,7 @@ CPU 上下文切换,是保证 Linux 系统正常工作的核心功能之一,
|
||||
|
||||
## CPU 上下文切换分类
|
||||
|
||||
CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置, 运行新任务。
|
||||
CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU 寄存器和程序计数器)保存起来,然后加载新任务的上下文到这些寄存器和程序计数器,最后再跳转到程序计数器所指的新位置,运行新任务。
|
||||
|
||||
根据任务的不同,CPU 的上下文切换就可以分为 __进程上下文切换__、 __线程上下文切换__ 以及 __中断上下文切换__
|
||||
|
||||
@ -18,8 +18,8 @@ CPU 上下文切换,就是先把前一个任务的 CPU 上下文(也就是 CPU
|
||||
|
||||
Linux 按照特权等级,把进程的运行空间分为内核空间和用户空间,CPU 特权等级的 Ring 0 和 Ring 3。
|
||||
|
||||
内核空间(Ring 0)具有最高权限,可以直接访问所有资源;
|
||||
用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统 调用陷入到内核中,才能访问这些特权资源。
|
||||
内核空间(Ring 0))具有最高权限,可以直接访问所有资源;
|
||||
用户空间(Ring 3)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统 调用陷入到内核中,才能访问这些特权资源。
|
||||
|
||||
进程既可以在用户空间运行,又可以在内核空间中运行。进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。
|
||||
|
||||
@ -36,11 +36,11 @@ CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着
|
||||
|
||||
#### 进程在什么时候才会被调度到 CPU 上运行
|
||||
|
||||
最容易想到的一个时机,就是进程执行完终止了,它之前使用的 CPU 会释放出来,这个时候再从就绪队列里,拿一个新的进程过来运行。其实还有很多其他场景,也会触发进程调度
|
||||
最容易想到的一个时机,就是进程执行完终止了,它之前使用的 CPU 会释放出来,这个时候再从就绪队列里,拿一个新的进程过来运行。其实还有很多其他场景,也会触发进程调度。
|
||||
|
||||
其一,为了保证所有进程可以得到公平调度,CPU 时间被划分为一段段的时间片,这些时间片再被轮流分配给各个进程。这样,当某个进程的时间片耗尽了,就会被系统挂起,切换到其它正在等待 CPU 的进程运行。
|
||||
|
||||
其二,进程在系统资源不足(比如内存不足)时,要等到资源满足后才可以运行,这个时
|
||||
其二,进程在系统资源不足(比如内存不足)时,要等到资源满足后才可以运行,这个时
|
||||
候进程也会被挂起,并由系统调度其他进程运行。
|
||||
|
||||
其三,当进程通过睡眠函数 sleep 这样的方法将自己主动挂起时,自然也会重新调度。
|
||||
@ -59,7 +59,7 @@ __线程与进程最大的区别在于,线程是调度的基本单位,而进
|
||||
|
||||
所以,对于线程和进程,我们可以这么理解:__当进程只有一个线程时,可以认为进程就等于线程__。当进程拥有多个线程时,这些线程会共享相同的虚拟内存和全局变量等资源。这些资源在上下文切换时是不需要修改的。另外,线程也有自己的私有数据,比如栈和寄存器等,这些在上下文换时也是需要保存的。
|
||||
|
||||
线程的上下文切换其实就可以分为两种情况:
|
||||
线程的上下文切换其实就可以分为两种情况:
|
||||
|
||||
第一种, 前后两个线程属于不同进程。此时,因为资源不共享,所以切换过程就跟进程上下文切换是一样。
|
||||
|
||||
@ -80,7 +80,7 @@ __线程与进程最大的区别在于,线程是调度的基本单位,而进
|
||||
|
||||
vmstat 是一个常用的系统性能分析工具,主要用来分析系统的内存使用情况,也常用来分 析 CPU 上下文切换和中断的次数。
|
||||
|
||||
下面就是一个 vmstat 的使用示例:
|
||||
下面就是一个 vmstat 的使用示例:
|
||||
|
||||
```
|
||||
vmstat 5 #每隔 5 秒输出 1 组数据
|
||||
@ -94,19 +94,19 @@ procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
|
||||
|
||||
结果含义说明
|
||||
|
||||
- cs(context switch)是每秒上下文切换的次数。
|
||||
- cs(context switch)是每秒上下文切换的次数。
|
||||
|
||||
- in(interrupt)则是每秒中断的次数。
|
||||
- in(interrupt)则是每秒中断的次数。
|
||||
|
||||
- r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
|
||||
- r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
|
||||
|
||||
- b(Blocked)则是处于不可中断睡眠状态的进程数。
|
||||
- b(Blocked)则是处于不可中断睡眠状态的进程数。
|
||||
|
||||
可以看到,这个例子中的上下文切换次数 cs 是 8 次,而系统中断次数 in 则是 2 次,而 就绪队列长度 r 和不可中断状态进程数 b 都是 0。
|
||||
|
||||
vmstat 只给出了系统总体的上下文切换情况,要想查看每个进程的详细情况,就需要使用我们前面提到过的 pidstat 了。给它加上 -w 选项,你就可以查看每个进程上下文切换的情况了。
|
||||
|
||||
示例:
|
||||
示例:
|
||||
|
||||
```
|
||||
pidstat -w 5 # 每隔 5 秒输出 1 组数据
|
||||
@ -123,7 +123,7 @@ Linux 4.4.0-142-generic (10-53-166-171) 07/07/2019 _x86_64_ (2 CPU)
|
||||
04:05:58 PM 0 10 0.20 0.00 watchdog/0
|
||||
```
|
||||
|
||||
这个结果中有两列内容是我们的重点关注对象。一个是 cswch ,表示每秒自愿上下文切换 (voluntary context switches)的次数,另一个则是 nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。
|
||||
这个结果中有两列内容是我们的重点关注对象。一个是 cswch ,表示每秒自愿上下文切换 (voluntary context switches)的次数,另一个则是 nvcswch ,表示每秒非自愿上下文切换(non voluntary context switches)的次数。
|
||||
|
||||
这两个概念一定要牢牢记住,因为它们意味着不同的性能问题:
|
||||
|
||||
|
28
cpu-used.md
28
cpu-used.md
@ -4,9 +4,9 @@ CPU 使用率是单位时间内 CPU 使用情况的统计,以百分比的方
|
||||
|
||||
## 怎么查看 CPU 使用率
|
||||
|
||||
top 和 ps 是最常用的性能分析工具:top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况。ps 则只显示了每个进程的资源使用情况。
|
||||
top 和 ps 是最常用的性能分析工具:top 显示了系统总体的 CPU 和内存使用情况,以及各个进程的资源使用情况。ps 则只显示了每个进程的资源使用情况。
|
||||
|
||||
top 默认每 3 秒刷新一次,输出格式为:
|
||||
top 默认每 3 秒刷新一次,输出格式为:
|
||||
|
||||
```
|
||||
top - 21:12:50 up 21 days, 23:13, 2 users, load average: 0.05, 0.04, 0.01
|
||||
@ -36,17 +36,17 @@ KiB Swap: 0 total, 0 free, 0 used. 3576656 avail Mem
|
||||
top 并没有细分进程的用户态 CPU 和内核态 CPU,需要查看每个进程的详细情况,可以用 pidstat ,它正是一个专门分析每个进程 CPU 使用情况的工具。
|
||||
|
||||
|
||||
下面的 pidstat 命令,就间隔 1 秒展示了进程的 5 组 CPU 使用率,包括:
|
||||
下面的 pidstat 命令,就间隔 1 秒展示了进程的 5 组 CPU 使用率,包括:
|
||||
|
||||
- 用户态 CPU 使用率 (%usr)
|
||||
- 用户态 CPU 使用率(%usr)
|
||||
|
||||
- 内核态 CPU 使用率(%system)
|
||||
- 内核态 CPU 使用率(%system)
|
||||
|
||||
- 运行虚拟机 CPU 使用率(%guest)
|
||||
- 运行虚拟机 CPU 使用率(%guest)
|
||||
|
||||
- 等待 CPU 使用率(%wait)
|
||||
- 等待 CPU 使用率(%wait)
|
||||
|
||||
- 以及总的 CPU 使用率(%CPU)
|
||||
- 以及总的 CPU 使用率(%CPU)
|
||||
|
||||
最后的 Average 部分,还计算了 5 组数据的平均值。
|
||||
|
||||
@ -78,13 +78,13 @@ Average: 113 4606 0.20 0.20 0.00 0.40 - beam.smp
|
||||
|
||||
## CPU 使用率过高怎么办
|
||||
|
||||
通过 top、ps、pidstat 等工具,你能够轻松找到 CPU 使用率较高(比如 100% )的进程,如果需要排查占用 CPU 的到底是代码里的哪个函数,推荐使用 perf。perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
|
||||
通过 top、ps、pidstat 等工具,你能够轻松找到 CPU 使用率较高(比如 100% )的进程,如果需要排查占用 CPU 的到底是代码里的哪个函数,推荐使用 perf。perf 是 Linux 2.6.31 以后内置的性能分析工具。它以性能事件采样为基础,不仅可以分析系统的各种事件和内核性能,还可以用来分析指定应用程序的性能问题。
|
||||
|
||||
perf 分析 CPU 性能问题,两种最常见用法
|
||||
|
||||
__第一种__
|
||||
|
||||
perf top,类似于 top,它能够实时显示占用 CPU 时钟最多的函数或 者指令,因此可以用来查找热点函数,使用界面如下所示:
|
||||
perf top,类似于 top,它能够实时显示占用 CPU 时钟最多的函数或 者指令,因此可以用来查找热点函数,使用界面如下所示:
|
||||
|
||||
```
|
||||
sudo perf top
|
||||
@ -110,15 +110,15 @@ Overhead Shared Object Symbol
|
||||
1.46% perf [.] 0x000000000008e326
|
||||
```
|
||||
|
||||
输出结果中,第一行包含三个数据,分别是采样数(Samples)、事件类型(event)和事件总数量(Event count)。比如这个例子中,perf 总共采集了 674 个 CPU 时间事件,而总事件数则为 149937500
|
||||
输出结果中,第一行包含三个数据,分别是采样数(Samples)、事件类型(event)和事件总数量(Event count)。比如这个例子中,perf 总共采集了 674 个 CPU 时间事件,而总事件数则为 149937500
|
||||
|
||||
另外,采样数需要我们特别注意。如果采样数过少(比如只有十几个),那下面的排序和 百分比就没什么实际参考价值了。
|
||||
另外,采样数需要我们特别注意。如果采样数过少(比如只有十几个),那下面的排序和 百分比就没什么实际参考价值了。
|
||||
|
||||
再往下看是一个表格式样的数据,每一行包含四列,分别是:
|
||||
再往下看是一个表格式样的数据,每一行包含四列,分别是:
|
||||
|
||||
- 第一列 Overhead ,是该符号的性能事件在所有采样中的比例,用百分比来表示。
|
||||
|
||||
- 第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
|
||||
- 第二列 Shared ,是该函数或指令所在的动态共享对象(Dynamic Shared Object),如内核、进程名、动态链接库名、内核模块名等。
|
||||
|
||||
- 第三列 Object ,是动态共享对象的类型。比如 [.] 表示用户空间的可执行程序、或者动态链接库,而 [k] 则表示内核空间。
|
||||
|
||||
|
329
package-lock.json
generated
329
package-lock.json
generated
@ -1,330 +1,3 @@
|
||||
{
|
||||
"requires": true,
|
||||
"lockfileVersion": 1,
|
||||
"dependencies": {
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
},
|
||||
"cheerio": {
|
||||
"version": "0.22.0",
|
||||
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-0.22.0.tgz",
|
||||
"integrity": "sha1-qbqoYKP5tZWmuBsahocxIe06Jp4=",
|
||||
"requires": {
|
||||
"css-select": "~1.2.0",
|
||||
"dom-serializer": "~0.1.0",
|
||||
"entities": "~1.1.1",
|
||||
"htmlparser2": "^3.9.1",
|
||||
"lodash.assignin": "^4.0.9",
|
||||
"lodash.bind": "^4.1.4",
|
||||
"lodash.defaults": "^4.0.1",
|
||||
"lodash.filter": "^4.4.0",
|
||||
"lodash.flatten": "^4.2.0",
|
||||
"lodash.foreach": "^4.3.0",
|
||||
"lodash.map": "^4.4.0",
|
||||
"lodash.merge": "^4.4.0",
|
||||
"lodash.pick": "^4.2.1",
|
||||
"lodash.reduce": "^4.4.0",
|
||||
"lodash.reject": "^4.4.0",
|
||||
"lodash.some": "^4.4.0"
|
||||
}
|
||||
},
|
||||
"css-select": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-1.2.0.tgz",
|
||||
"integrity": "sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg=",
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0",
|
||||
"css-what": "2.1",
|
||||
"domutils": "1.5.1",
|
||||
"nth-check": "~1.0.1"
|
||||
}
|
||||
},
|
||||
"css-what": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npm.taobao.org/css-what/download/css-what-2.1.3.tgz",
|
||||
"integrity": "sha1-ptdgRXM2X+dGhsPzEcVlE9iChfI="
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npm.taobao.org/dom-serializer/download/dom-serializer-0.1.1.tgz",
|
||||
"integrity": "sha1-HsQFnihLq+027sKUHUqXChic58A=",
|
||||
"requires": {
|
||||
"domelementtype": "^1.3.0",
|
||||
"entities": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npm.taobao.org/domelementtype/download/domelementtype-1.3.1.tgz",
|
||||
"integrity": "sha1-0EjESzew0Qp/Kj1f7j9DM9eQSB8="
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-2.4.2.tgz",
|
||||
"integrity": "sha1-iAUJfpM9ZehVRvcm1g9euItE+AM=",
|
||||
"requires": {
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz",
|
||||
"integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=",
|
||||
"requires": {
|
||||
"dom-serializer": "0",
|
||||
"domelementtype": "1"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npm.taobao.org/entities/download/entities-1.1.2.tgz",
|
||||
"integrity": "sha1-vfpzUplmTfr9NFKe1PhSKidf6lY="
|
||||
},
|
||||
"gitbook-plugin-3-ba": {
|
||||
"version": "0.9.0",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-3-ba/-/gitbook-plugin-3-ba-0.9.0.tgz",
|
||||
"integrity": "sha1-uR3Q7fCHYSeC/hdzkXfuJDSj1X4="
|
||||
},
|
||||
"gitbook-plugin-anchors": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-anchors/-/gitbook-plugin-anchors-0.7.1.tgz",
|
||||
"integrity": "sha1-j1hbmasaYC6nFDQiWMlXI4427II=",
|
||||
"requires": {
|
||||
"cheerio": "*",
|
||||
"github-slugid": "1.0.1"
|
||||
}
|
||||
},
|
||||
"gitbook-plugin-back-to-top-button": {
|
||||
"version": "0.1.4",
|
||||
"resolved": "https://registry.npm.taobao.org/gitbook-plugin-back-to-top-button/download/gitbook-plugin-back-to-top-button-0.1.4.tgz",
|
||||
"integrity": "sha1-5iGDOLDvGdWOb2YAmUNQt26ANd8="
|
||||
},
|
||||
"gitbook-plugin-copy-code-button": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/gitbook-plugin-copy-code-button/download/gitbook-plugin-copy-code-button-0.0.2.tgz",
|
||||
"integrity": "sha1-Q0UzIAtc9ZbChMFOHYu1d3IIRHU="
|
||||
},
|
||||
"gitbook-plugin-disqus": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-disqus/-/gitbook-plugin-disqus-0.1.0.tgz",
|
||||
"integrity": "sha1-9gNfnEmHz1/JGA4FpkQ1pngpatY="
|
||||
},
|
||||
"gitbook-plugin-donate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-donate/-/gitbook-plugin-donate-1.0.2.tgz",
|
||||
"integrity": "sha1-telSLNaTFY4a/ueAtfATk/0yP2Q="
|
||||
},
|
||||
"gitbook-plugin-edit-link": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-edit-link/-/gitbook-plugin-edit-link-2.0.2.tgz",
|
||||
"integrity": "sha1-2PzZJ+ztgeemYqctWdtgnq/X5y8="
|
||||
},
|
||||
"gitbook-plugin-favicon": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-favicon/-/gitbook-plugin-favicon-0.0.2.tgz",
|
||||
"integrity": "sha1-s+QWQvFSr8bEU1/ZtjXf4xtMh3I="
|
||||
},
|
||||
"gitbook-plugin-github": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-github/-/gitbook-plugin-github-2.0.0.tgz",
|
||||
"integrity": "sha1-UWbnY8/MQC1DKIC3pshcHFS1ao0="
|
||||
},
|
||||
"gitbook-plugin-page-footer-ex": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npm.taobao.org/gitbook-plugin-page-footer-ex/download/gitbook-plugin-page-footer-ex-0.1.2.tgz",
|
||||
"integrity": "sha1-AgbTvTuDSTyVIUR3ynajak5CyhM=",
|
||||
"requires": {
|
||||
"moment": "^2.10.6"
|
||||
}
|
||||
},
|
||||
"gitbook-plugin-search": {
|
||||
"version": "2.2.1",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-search/-/gitbook-plugin-search-2.2.1.tgz",
|
||||
"integrity": "sha1-bSW1p3aZD6mP39+jfeMx944PaxM="
|
||||
},
|
||||
"gitbook-plugin-search-pro": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-search-pro/-/gitbook-plugin-search-pro-2.0.2.tgz",
|
||||
"integrity": "sha1-fOduj2XCBESJucaSc2sj+B/mofI=",
|
||||
"requires": {
|
||||
"html-entities": "1.2.0"
|
||||
}
|
||||
},
|
||||
"gitbook-plugin-sharing-plus": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-sharing-plus/-/gitbook-plugin-sharing-plus-0.0.2.tgz",
|
||||
"integrity": "sha1-FstYGACikvAbvY19Ic6jID0Jcz8=",
|
||||
"requires": {
|
||||
"lodash": "^3.10.1"
|
||||
}
|
||||
},
|
||||
"gitbook-plugin-sitemap": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-sitemap/-/gitbook-plugin-sitemap-1.2.0.tgz",
|
||||
"integrity": "sha1-hneZN1C5ZYOMkG/nz8CiB8DQbcs=",
|
||||
"requires": {
|
||||
"sitemap": "1.5.0"
|
||||
}
|
||||
},
|
||||
"gitbook-plugin-splitter": {
|
||||
"version": "0.0.8",
|
||||
"resolved": "https://registry.npmjs.org/gitbook-plugin-splitter/-/gitbook-plugin-splitter-0.0.8.tgz",
|
||||
"integrity": "sha1-8rBRMGD8kma0awQYLk7KHUtx+vw="
|
||||
},
|
||||
"github-slugid": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/github-slugid/-/github-slugid-1.0.1.tgz",
|
||||
"integrity": "sha1-vM3QgVv61p2KNZ+k/WWUfWBuw8A="
|
||||
},
|
||||
"html-entities": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.2.0.tgz",
|
||||
"integrity": "sha1-QZSMr4XOgv7Tbk5qDtNxpmZDeeI="
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npm.taobao.org/htmlparser2/download/htmlparser2-3.10.1.tgz",
|
||||
"integrity": "sha1-vWedw/WYl7ajS7EHSchVu1OpOS8=",
|
||||
"requires": {
|
||||
"domelementtype": "^1.3.1",
|
||||
"domhandler": "^2.3.0",
|
||||
"domutils": "^1.5.1",
|
||||
"entities": "^1.1.1",
|
||||
"inherits": "^2.0.1",
|
||||
"readable-stream": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"lodash": {
|
||||
"version": "3.10.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz",
|
||||
"integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y="
|
||||
},
|
||||
"lodash.assignin": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assignin/-/lodash.assignin-4.2.0.tgz",
|
||||
"integrity": "sha1-uo31+4QesKPoBEIysOJjqNxqKKI="
|
||||
},
|
||||
"lodash.bind": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.bind/-/lodash.bind-4.2.1.tgz",
|
||||
"integrity": "sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU="
|
||||
},
|
||||
"lodash.defaults": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
|
||||
"integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
|
||||
},
|
||||
"lodash.filter": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.filter/-/lodash.filter-4.6.0.tgz",
|
||||
"integrity": "sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4="
|
||||
},
|
||||
"lodash.flatten": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
|
||||
"integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
|
||||
},
|
||||
"lodash.foreach": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz",
|
||||
"integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM="
|
||||
},
|
||||
"lodash.map": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz",
|
||||
"integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM="
|
||||
},
|
||||
"lodash.merge": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.1.tgz",
|
||||
"integrity": "sha1-rcJdnLmbk5HFliTzefu6YNcRHVQ="
|
||||
},
|
||||
"lodash.pick": {
|
||||
"version": "4.4.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.pick/-/lodash.pick-4.4.0.tgz",
|
||||
"integrity": "sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM="
|
||||
},
|
||||
"lodash.reduce": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.reduce/-/lodash.reduce-4.6.0.tgz",
|
||||
"integrity": "sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs="
|
||||
},
|
||||
"lodash.reject": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.reject/-/lodash.reject-4.6.0.tgz",
|
||||
"integrity": "sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU="
|
||||
},
|
||||
"lodash.some": {
|
||||
"version": "4.6.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.some/-/lodash.some-4.6.0.tgz",
|
||||
"integrity": "sha1-G7nzFO9ri63tE7VJFpsqlF62jk0="
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.24.0",
|
||||
"resolved": "https://registry.npm.taobao.org/moment/download/moment-2.24.0.tgz",
|
||||
"integrity": "sha1-DQVdU/UFKqZTyfbraLtdEr9cK1s="
|
||||
},
|
||||
"nth-check": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npm.taobao.org/nth-check/download/nth-check-1.0.2.tgz",
|
||||
"integrity": "sha1-sr0pXDfj3VijvwcAN2Zjuk2c8Fw=",
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "3.3.0",
|
||||
"resolved": "https://registry.npm.taobao.org/readable-stream/download/readable-stream-3.3.0.tgz",
|
||||
"integrity": "sha1-y4ARqtAC63F78EApH+uoVpyYb7k=",
|
||||
"requires": {
|
||||
"inherits": "^2.0.3",
|
||||
"string_decoder": "^1.1.1",
|
||||
"util-deprecate": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
|
||||
},
|
||||
"sitemap": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/sitemap/-/sitemap-1.5.0.tgz",
|
||||
"integrity": "sha1-RbPoib96XbDvvyxMb8sVbKh+EgE=",
|
||||
"requires": {
|
||||
"underscore": "^1.7.0",
|
||||
"url-join": "^0.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npm.taobao.org/string_decoder/download/string_decoder-1.2.0.tgz",
|
||||
"integrity": "sha1-/obnOLGVRK/nBGkkOyoe6SQOro0=",
|
||||
"requires": {
|
||||
"safe-buffer": "~5.1.0"
|
||||
}
|
||||
},
|
||||
"underscore": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npm.taobao.org/underscore/download/underscore-1.9.1.tgz",
|
||||
"integrity": "sha1-BtzjSg5op7q8KbNluOdLiSUgOWE="
|
||||
},
|
||||
"url-join": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/url-join/-/url-join-0.0.1.tgz",
|
||||
"integrity": "sha1-HbSK1CLTQCRpqH99l73r/k+x48g="
|
||||
},
|
||||
"util-deprecate": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
|
||||
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
|
||||
}
|
||||
}
|
||||
"lockfileVersion": 1
|
||||
}
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
简单来说,平均负载是指单位时间内,系统处于__可运行状态__和__不可中断状态__的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。
|
||||
|
||||
所谓可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。
|
||||
所谓可运行状态的进程,是指正在使用 CPU 或者正在等待 CPU 的进程,也就是我们常用 ps 命令看到的,处于 R 状态(Running 或 Runnable)的进程。
|
||||
|
||||
不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态 (Uninterruptible Sleep,也称为 Disk Sleep)的进程。
|
||||
不可中断状态的进程则是正处于内核态关键流程中的进程,并且这些流程是不可打断的,比如最常见的是等待硬件设备的 I/O 响应,也就是我们在 ps 命令中看到的 D 状态 (Uninterruptible Sleep,也称为 Disk Sleep)的进程。
|
||||
|
||||
比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是
|
||||
不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程
|
||||
|
@ -1,6 +1,6 @@
|
||||
## 什么是不可中断状态
|
||||
|
||||
当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从 ps 或者 top 命令的输出中,可以发现它们都处于 D 状态,也就是不可中断状态 (Uninterruptible Sleep)。
|
||||
当 iowait 升高时,进程很可能因为得不到硬件的响应,而长时间处于不可中断状态。从 ps 或者 top 命令的输出中,可以发现它们都处于 D 状态,也就是不可中断状态 (Uninterruptible Sleep)。
|
||||
|
||||
不可中断状态,表示进程正在跟硬件交互,为了保护进程数据和硬件的一致性,系统不允许其他进程或中断打断这个进程。进程长时间处于不可中断状态,通常表示系统有 I/O 性能问题。
|
||||
|
||||
@ -10,8 +10,7 @@
|
||||
|
||||
特别是,中断处理程序在响应中断时,还会临时关闭中断。这就会导致上一次中断处理完成之前,其他中断都不能响应,也就是说中断有可能会丢失。
|
||||
|
||||
举个最常见的网卡接收数据包的例子:网卡接收到数据包后,会通过 __硬件中断__ 的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个 __软中断__ 信号,通知下半部做进一步的处理。而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据
|
||||
进行逐层解析和处理,直到把它送给应用程序。
|
||||
举个最常见的网卡接收数据包的例子:网卡接收到数据包后,会通过 __硬件中断__ 的方式,通知内核有新的数据到了。这时,内核就应该调用中断处理程序来响应它。对上半部来说,既然是快速处理,其实就是要把网卡的数据读到内存中,然后更新一下硬件寄存器的状态(表示数据已经读好了),最后再发送一个 __软中断__ 信号,通知下半部做进一步的处理。而下半部被软中断信号唤醒后,需要从内存中找到网络数据,再按照网络协议栈,对数据进行逐层解析和处理,直到把它送给应用程序。
|
||||
|
||||
Linux 将中断处理过程分成了两个阶段,也就是上半部和下半部:
|
||||
|
||||
@ -24,7 +23,7 @@ Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类
|
||||
|
||||
## 什么是僵死(僵尸)进程
|
||||
|
||||
僵死(僵尸)进程进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死(僵尸)。
|
||||
僵死(僵尸)进程:一个进程使用 fork 创建子进程,如果子进程退出,而父进程并没有调用 wait() 或 waitpid() 获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死(僵尸)。
|
||||
|
||||
通常,僵尸进程持续的时间都比较短,在父进程回收它的资源后就会消亡;或者在父进程退出后,由 init 进程回收后也会消亡。
|
||||
|
||||
@ -32,7 +31,7 @@ Linux 中的软中断包括网络收发、定时、调度、RCU 锁等各种类
|
||||
|
||||
#### top 命令查看进程状态
|
||||
|
||||
top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。
|
||||
top 和 ps 是最常用的查看进程状态的工具,我们就从 top 的输出开始。下面是一个 top 命令输出的示例,S 列(也就是 Status 列)表示进程的状态。
|
||||
|
||||
```
|
||||
top - 21:43:31 up 28 days, 23:44, 2 users, load average: 0.02, 0.02, 0.00
|
||||
@ -52,15 +51,15 @@ KiB Swap: 0 total, 0 free, 0 used. 3169024 avail Mem
|
||||
|
||||
- __R__ 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正在等待运行。
|
||||
|
||||
- __D__ 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般 表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
|
||||
- __D__ 是 Disk Sleep 的缩写,也就是不可中断状态睡眠(Uninterruptible Sleep),一般表示进程正在跟硬件交互,并且交互过程不允许被其他进程或中断打断。
|
||||
|
||||
- __Z__ 是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它 表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
|
||||
- __Z__ 是 Zombie 的缩写,如果你玩过“植物大战僵尸”这款游戏,应该知道它的意思。它 表示僵尸进程,也就是进程实际上已经结束了,但是父进程还没有回收它的资源(比如进程的描述符、PID 等)。
|
||||
|
||||
- __S__ 是 Interruptible Sleep 的缩写,也就是可中断状态睡眠,表示进程因为等待某个事件 而被系统挂起。当进程等待的事件发生时,它会被唤醒并进入 R 状态。
|
||||
|
||||
- __I__ 是 Idle 的缩写,也就是空闲状态,用在不可中断睡眠的内核线程上。前面说了,硬件交互导致的不可中断进程用 D 表示,但对某些内核线程来说,它们有可能实际上并没有任何负载,用 Idle 正是为了区分这种情况。要注意,D 状态的进程会导致平均负载升高, I 状态的进程却不会。
|
||||
|
||||
- __T__ 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你 用 fg 命令,恢复到前台运行)。而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪 状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
|
||||
- __T__ 或者 t,也就是 Stopped 或 Traced 的缩写,表示进程处于暂停或者跟踪状态。向一个进程发送 SIGSTOP 信号,它就会因响应这个信号变成暂停状态(Stopped);再向它发送 SIGCONT 信号,进程又会恢复运行(如果进程是终端里直接启动的,则需要你 用 fg 命令,恢复到前台运行)。而当你用调试器(如 gdb)调试一个进程时,在使用断点中断进程后,进程就会变成跟踪状态,这其实也是一种特殊的暂停状态,只不过你可以用调试器来跟踪并按需要控制进程的运行。
|
||||
|
||||
- __X__ 是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。
|
||||
|
||||
@ -79,4 +78,4 @@ root 12913 0.0 0.0 12944 928 pts/1 S+ 21:55 0:00 grep --color=au
|
||||
|
||||
进程组和会话。它们用来管理一组相互关联的进程,进程组表示一组相互关联的进程,比如每个子进程都是父进程所在组的成员;而会话是指共享同一个控制终端的一个或多个进程组。
|
||||
|
||||
比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。
|
||||
比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。
|
Loading…
x
Reference in New Issue
Block a user