From b0367180dbcf25b0d248702cd36a4540d8168c8a Mon Sep 17 00:00:00 2001 From: nick Date: Tue, 21 Jan 2020 11:26:58 +0800 Subject: [PATCH] :pencil2: update --- cpu-context.md | 30 +- cpu-used.md | 30 +- package-lock.json | 329 +----------------- stress-sysstat-mpstat-pidstat-watch-uptime.md | 6 +- zombie-process.md | 23 +- 5 files changed, 45 insertions(+), 373 deletions(-) diff --git a/cpu-context.md b/cpu-context.md index 395dd99..0b2ce40 100644 --- a/cpu-context.md +++ b/cpu-context.md @@ -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)只能访问受限资源,不能直接访问内存等硬件设备,必须通过系统 调用陷入到内核中,才能访问这些特权资源。 进程既可以在用户空间运行,又可以在内核空间中运行。进程在用户空间运行时,被称为进程的用户态,而陷入内核空间的时候,被称为进程的内核态。 @@ -29,18 +29,18 @@ Linux 按照特权等级,把进程的运行空间分为内核空间和用户 CPU 寄存器里原来用户态的指令位置,需要先保存起来。接着,为了执行内核态代码,CPU 寄存器需要更新为内核态指令的新位置。最后才是跳转到内核态运行内核任务。 -而系统调用结束后,CPU 寄存器需要 __恢复__原来保存的用户态,然后再切换到用户空间,继续运行进程。所以, __一次系统调用的过程,其实是发生了两次 CPU 上下文切换__。 +而系统调用结束后,CPU 寄存器需要__恢复__原来保存的用户态,然后再切换到用户空间,继续运行进程。所以, __一次系统调用的过程,其实是发生了两次 CPU 上下文切换__。 需要注意的是,系统调用过程中,并不会涉及到虚拟内存等进程用户态的资源,也 不会切换进程。这跟我们通常所说的进程上下文切换是不一样的: __进程上下文切换,是指从一个进程切换到另一个进程运行。而系统调用过程中一直是同一个进程在运行__ 。所以,__系统调用过程通常称为特权模式切换,而不是上下文切换__。但实际上,系统调用过程中,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)的次数。 这两个概念一定要牢牢记住,因为它们意味着不同的性能问题: diff --git a/cpu-used.md b/cpu-used.md index b70d9d2..de04f6a 100644 --- a/cpu-used.md +++ b/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] 则表示内核空间。 @@ -126,7 +126,7 @@ Overhead Shared Object Symbol __第二种__ -就是 perf record 和 perf report。 perf top 虽然实时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续的分析。 而 perf record 则提供了保存数据的功能,保存后的数据,需要你用 perf report 解析展示。 +就是 perf record 和 perf report。perf top 虽然实时展示了系统的性能信息,但它的缺点是并不保存数据,也就无法用于离线或者后续的分析。而 perf record 则提供了保存数据的功能,保存后的数据,需要你用 perf report 解析展示。 ``` sudo perf record -a #按 Ctrl+C 终止采样 diff --git a/package-lock.json b/package-lock.json index 95d00fe..48e341a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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 } diff --git a/stress-sysstat-mpstat-pidstat-watch-uptime.md b/stress-sysstat-mpstat-pidstat-watch-uptime.md index 6e86a79..f4a1e16 100644 --- a/stress-sysstat-mpstat-pidstat-watch-uptime.md +++ b/stress-sysstat-mpstat-pidstat-watch-uptime.md @@ -1,10 +1,10 @@ ## 什么平均负载 -简单来说,平均负载是指单位时间内,系统处于 __可运行状态__ 和 __不可中断状态__ 的平均进程数,也就是平均活跃进程数,它和 CPU 使用率并没有直接关系。 +简单来说,平均负载是指单位时间内,系统处于__可运行状态__和__不可中断状态__的平均进程数,也就是平均活跃进程数,它和 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)的进程。 比如,当一个进程向磁盘读写数据时,为了保证数据的一致性,在得到磁盘回复前,它是 不能被其他进程或者中断打断的,这个时候的进程就处于不可中断状态。如果此时的进程 diff --git a/zombie-process.md b/zombie-process.md index 0cfe985..c34388c 100644 --- a/zombie-process.md +++ b/zombie-process.md @@ -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 @@ -50,19 +49,19 @@ KiB Swap: 0 total, 0 free, 0 used. 3169024 avail Mem 3 root 20 0 0 0 0 S 0.0 0.0 0:33.16 ksoftirqd/0 ``` -- __R__ 是 Running 或 Runnable 的缩写,表示进程在 CPU 的就绪队列中,正在运行或者正 在等待运行。 +- __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 状态的进程却不会。 +- __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 命令 中看到它。 +- __X__ 是 Dead 的缩写,表示进程已经消亡,所以你不会在 top 或者 ps 命令中看到它。 #### 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),这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。 \ No newline at end of file +比如,我们通过 SSH 登录服务器,就会打开一个控制终端(TTY),这个控制终端就对应 一个会话。而我们在终端中运行的命令以及它们的子进程,就构成了一个个的进程组,其中,在后台运行的命令,构成后台进程组;在前台运行的命令,构成前台进程组。 \ No newline at end of file