✏️ update

This commit is contained in:
nick 2020-01-21 11:26:58 +08:00
parent 370cd588bc
commit b0367180db
5 changed files with 45 additions and 373 deletions

View File

@ -1,6 +1,6 @@
## 什么是 CPU 上下文
Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们造成多任务同时运行的错觉。而在每个任务运行前CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器(Program CounterPC)
Linux 是一个多任务操作系统,它支持远大于 CPU 数量的任务同时运行。当然,这些任务实际上并不是真的在同时运行,而是因为系统在很短的时间内,将 CPU 轮流分配给它们造成多任务同时运行的错觉。而在每个任务运行前CPU 都需要知道任务从哪里加载、又从哪里开始运行,也就是说,需要系统事先帮它设置好 CPU 寄存器和程序计数器Program CounterPC
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)是每秒上下文切换的次数。
- cscontext switch是每秒上下文切换的次数。
- in(interrupt)则是每秒中断的次数。
- ininterrupt则是每秒中断的次数。
- r(Running or Runnable)是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
- rRunning or Runnable是就绪队列的长度,也就是正在运行和等待 CPU 的进程数。
- b(Blocked)则是处于不可中断睡眠状态的进程数。
- bBlocked则是处于不可中断睡眠状态的进程数。
可以看到,这个例子中的上下文切换次数 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的次数。
这两个概念一定要牢牢记住,因为它们意味着不同的性能问题:

View File

@ -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
View File

@ -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
}

View File

@ -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的进程。
比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是
不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程

View File

@ -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,这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。