标签 内存 下的文章

对于 Linux 管理员来说,检查系统内存用量是一个重要的技能。Jack 给出了解决这个问题的五种不同方式。

Linux 操作系统包含大量工具,所有这些工具都可以帮助你管理系统。从简单的文件和目录工具到非常复杂的安全命令,在 Linux 中没有多少是你做不了的。而且,尽管普通桌面用户可能不需要在命令行熟悉这些工具,但对于 Linux 管理员来说,它们是必需的。为什么?首先,你在某些时候不得不使用没有 GUI 的 Linux 服务器。其次,命令行工具通常比 GUI 替代工具提供更多的功能和灵活性。

确定内存使用情况是你可能需要的技能,尤其是某个应用程序变得异常和占用系统内存时。当发生这种情况时,知道有多种工具可以帮助你进行故障排除十分方便的。或者,你可能需要收集有关 Linux 交换分区的信息,或者有关安装的内存的详细信息?对于这些也有相应的命令。让我们深入了解各种 Linux 命令行工具,以帮助你检查系统内存使用情况。这些工具并不是非常难以使用,在本文中,我将向你展示五种不同的方法来解决这个问题。

我将在 Ubuntu 18.04 服务器平台上进行演示,但是你应该在你选择的发行版中找到对应的所有命令。更妙的是,你不需要安装任何东西(因为大多数这些工具都包含 Linux 系统中)。

话虽如此,让我们开始工作吧。

top

我想从最常用的工具开始。top 命令提供正在运行的系统的实时动态视图,它检查每个进程的内存使用情况。这非常重要,因为你可以轻松地看到同一命令的多个示例消耗不同的内存量。虽然你无法在没有显示器的服务器上看到这种情况,但是你已经注意到打开 Chrome 使你的系统速度变慢了。运行 top 命令以查看 Chrome 有多个进程在运行(每个选项卡一个 - 图 1)。

 title=

图1:top 命令中出现多个 Chrome 进程。

Chrome 并不是唯一显示多个进程的应用。你看到图 1 中的 Firefox 了吗?那是 Firefox 的主进程,而 Web Content 进程是其打开的选项卡。在输出的顶部,你将看到系统统计信息。在我的机器上(System76 Leopard Extreme),我总共有 16GB 可用 RAM,其中只有超过 10GB 的 RAM 正在使用中。然后,你可以整理该列表,查看每个进程使用的内存百分比。

top 最好的地方之一就是发现可能已经失控的服务的进程 ID 号(PID)。有了这些 PID,你可以对有问题的任务进行故障排除(或 kill)。

如果你想让 top 显示更友好的内存信息,使用命令 top -o %MEM,这会使 top 按进程所用内存对所有进程进行排序(图 2)。

 title=

图 2:在 top 命令中按使用内存对进程排序

top 命令还为你提供有关使用了多少交换空间的实时更新。

free

然而有时候,top 命令可能不能满足你的需求。你可能只需要查看系统的可用和已用内存。对此,Linux 还有 free 命令。free 命令显示:

  • 可用和已使用的物理内存总量
  • 系统中交换内存的总量
  • 内核使用的缓冲区和缓存

在终端窗口中,输入 free 命令。它的输出不是实时的,相反,你将获得的是当前空闲和已用内存的即时快照(图 3)。

 title=

图 3 :free 命令的输出简单明了。

当然,你可以通过添加 -m 选项来让 free 显示得更友好一点,就像这样:free -m。这将显示内存的使用情况,以 MB 为单位(图 4)。

 title=

图 4:free 命令以一种更易于阅读的形式输出。

当然,如果你的系统是很新的,你将希望使用 -g 选项(以 GB 为单位),比如 free -g

如果你需要知道内存总量,你可以添加 -t 选项,比如:free -mt。这将简单地计算每列中的内存总量(图 5)。

 title=

图 5:为你提供空闲的内存列。

vmstat

另一个非常方便的工具是 vmstat。这个特殊的命令是一个报告虚拟内存统计信息的小技巧。vmstat 命令将报告关于:

  • 进程
  • 内存
  • 分页
  • 阻塞 IO
  • 中断
  • 磁盘
  • CPU

使用 vmstat 的最佳方法是使用 -s 选项,如 vmstat -s。这将在单列中报告统计信息(这比默认报告更容易阅读)。vmstat 命令将提供比你需要的更多的信息(图 6),但更多的总是更好的(在这种情况下)。

 title=

图 6:使用 vmstat 命令来检查内存使用情况。

dmidecode

如果你想找到关于已安装的系统内存的详细信息,该怎么办?为此,你可以使用 dmidecode 命令。这个特殊的工具是 DMI 表解码器,它将系统的 DMI 表内容转储成人类可读的格式。如果你不清楚 DMI 表是什么,那么可以这样说,它可以用来描述系统的构成(以及系统的演变)。

要运行 dmidecode 命令,你需要 sudo 权限。因此输入命令 sudo dmidecode -t 17。该命令的输出(图 7)可能很长,因为它显示所有内存类型设备的信息。因此,如果你无法上下滚动,则可能需要将该命令的输出发送到一个文件中,比如:sudo dmidecode -t 17> dmi_infoI,或将其传递给 less 命令,如 sudo dmidecode | less

 title=

图 7:dmidecode 命令的输出。

/proc/meminfo

你可能会问自己:“这些命令从哪里获取这些信息?”在某些情况下,它们从 /proc/meminfo 文件中获取。猜到了吗?你可以使用命令 less /proc/meminfo 直接读取该文件。通过使用 less 命令,你可以在长长的输出中向上和向下滚动,以准确找到你需要的内容(图 8)。

 title=

图 8:less /proc/meminfo 命令的输出。

关于 /proc/meminfo 你应该知道:这不是一个真实的文件。相反 /proc/meminfo 是一个虚拟文件,包含有关系统的实时动态信息。特别是,你需要检查以下值:

  • 全部内存(MemTotal
  • 空闲内存(MemFree
  • 可用内存(MemAvailable
  • 缓冲区(Buffers
  • 文件缓存(Cached
  • 交换缓存(SwapCached
  • 全部交换区(SwapTotal
  • 空闲交换区(SwapFree

如果你想使用 /proc/meminfo,你可以连接 egrep 命令使用它:egrep --color'Mem | Cache | Swap'/proc/meminfo。这将生成一个易于阅读的列表,其中包含 MemCacheSwap 等内容的条目将是彩色的(图 9)。

 title=

图 9:让 /proc/meminfo 更容易阅读。

继续学习

你要做的第一件事就是阅读每个命令的手册页(例如 man topman freeman vmstatman dmidecode)。从命令的手册页开始,对于如何在 Linux 上使用一个工具,它总是一个很好的学习方法。

通过 Linux 基金会和 edX 的免费 “Linux 简介”课程了解有关 Linux 的更多知识。


via: https://www.linux.com/learn/5-commands-checking-memory-usage-linux

作者:Jack Wallen 选题:lujun9972 译者:MjSeven 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

作为一名博客作者,我收藏了很多博客、网站和论坛用来寻找 Linux 和 Unix 相关的内容。有时候,我在浏览器中开启了非常多的标签页,导致操作系统会无响应好几分钟。我不能移动我的鼠标,也不能杀掉一个进程或关闭任何开启的标签页。在这种情况下,我别无选择,只能强制重启系统。当然我也用了 OneTab (LCTT 译注:OneTab 是一个 Chrome 的 Extension,可以将标签页转化成一个列表保存。)和 Greate Suspender (LCTT 译注:Great Suspender 是一个 Chrome 的 Extension, 可以自动冻结标签页)这样浏览器拓展,但它们在这里也起不到太大的作用。 我经常耗尽我的内存。而这就是 Early OOM 起作用的时候了。在情况严重时,它会杀掉一个未响应系统中的内存消耗最大的进程。Early OOM 每秒会检测可用内存和空余交换区 10 次,一旦两者都低于 10%,它就会把最大的进程杀死。

为什么用 Early OOM?为什么不用系统内置的 OOM killer?

在继续讨论下去之前,我想先简短的介绍下 OOM killer,也就是 Out Of Memory killer。OOM killer 是一个由内核在可用内存非常低的时候使用的进程。它的主要任务是不断的杀死进程,直到释放出足够的内存,使内核正在运行的其它进程能顺利运行。OOM killer 会找到系统中最不重要并且能释放出最多内存的进程,然后杀掉他们。在 /proc 目录下的 pid 目录中,我们可以看到每个进程的 oom_score

示例:

$ cat /proc/10299/oom_score
1

一个进程的 oom_score 的值越高,这个进程越有可能在系统内存耗尽的时候被 OOM killer 杀死。

Early OOM 的开发者表示,相对于内置的 OOM killer,Early OOM 有一个很大的优点。就像我之前说的那样,OOM killer 会杀掉 oom_score 最高的进程,而这也导致 Chrome 浏览器总是会成为第一个被杀死的进程。为了避免这种情况发生,Early OOM 使用 /proc/*/status 而不是 echo f > /proc/sysrq-trigger(LCTT 译注:这条命令会调用 OOM killer 杀死进程)。开发者还表示,手动触发 OOM killer 在最新版本的 Linux 内核中很可能不会起作用。

安装 Early OOM

Early OOM 在 AUR(Arch User Repository)中可以找到,所以你可以在 Arch 和它的衍生版本中使用任何 AUR 工具安装它。

使用 Pacaur

pacaur -S earlyoom

使用 Packer

packer -S earlyoom

使用 Yaourt

yaourt -S earlyoom

启用并启动 Early OOM 守护进程:

sudo systemctl enable earlyoom
sudo systemctl start earlyoom

在其它的 Linux 发行版中,可以按如下方法编译安装它:

git clone https://github.com/rfjakob/earlyoom.git
cd earlyoom
make
sudo make install

Early OOM - 杀掉无响应 Linux 系统中的最大的进程

运行如下命令启动 Early OOM:

earlyoom

如果是通过编译源代码安装的, 运行如下命令启动 Early OOM:

./earlyoom

示例输出:

earlyoom 0.12
mem total: 3863 MiB, min: 386 MiB (10 %)
swap total: 2047 MiB, min: 204 MiB (10 %)
mem avail: 1770 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1772 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1772 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1771 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1773 MiB (45 %), swap free: 2047 MiB (99 %)
mem avail: 1784 MiB (46 %), swap free: 2047 MiB (99 %)
[...]

就像你在上面的输出中可以看到的,Early OOM 将会显示你有多少内存和交换区,以及有多少可用的内存和交换区。记住它会一直保持运行,直到你按下 CTRL+C

如果可用的内存和交换区大小都低于 10%,Early OOM 将会自动杀死最大的进程,直到系统有足够的内存可以流畅的运行。你也可以根据你的需求配置最小百分比值。

设置最小的可用内存百分比,运行:

earlyoom -m <PERCENT_HERE>

设置最小可用交换区百分比, 运行:

earlyoom -s <PERCENT_HERE>

在帮助部分,可以看到更多详细信息:

$ earlyoom -h
earlyoom 0.12
Usage: earlyoom [OPTION]...

 -m PERCENT set available memory minimum to PERCENT of total (default 10 %)
 -s PERCENT set free swap minimum to PERCENT of total (default 10 %)
 -M SIZE set available memory minimum to SIZE KiB
 -S SIZE set free swap minimum to SIZE KiB
 -k use kernel oom killer instead of own user-space implementation
 -i user-space oom killer should ignore positive oom_score_adj values
 -d enable debugging messages
 -v print version information and exit
 -r INTERVAL memory report interval in seconds (default 1), set to 0 to
 disable completely
 -p set niceness of earlyoom to -20 and oom_score_adj to -1000
 -h this help text

现在,你再也不用担心内存消耗最高的进程了。希望这能给你帮助。更多的好内容将会到来,敬请期待。

谢谢!


via: https://www.ostechnix.com/kill-largest-process-unresponsive-linux-system/

作者:Aditya Goturu 译者:cizezsy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

学习 Linux 中的 大内存页 hugepage 。理解什么是“大内存页”,如何进行配置,如何查看当前状态以及如何禁用它。

Huge Pages in Linux

本文中我们会详细介绍 大内存页 huge page ,让你能够回答:Linux 中的“大内存页”是什么?在 RHEL6、RHEL7、Ubuntu 等 Linux 中,如何启用/禁用“大内存页”?如何查看“大内存页”的当前值?

首先让我们从“大内存页”的基础知识开始讲起。

Linux 中的“大内存页”是个什么玩意?

“大内存页”有助于 Linux 系统进行虚拟内存管理。顾名思义,除了标准的 4KB 大小的页面外,它们还能帮助管理内存中的巨大的页面。使用“大内存页”,你最大可以定义 1GB 的页面大小。

在系统启动期间,你能用“大内存页”为应用程序预留一部分内存。这部分内存,即被“大内存页”占用的这些存储器永远不会被交换出内存。它会一直保留其中,除非你修改了配置。这会极大地提高像 Oracle 数据库这样的需要海量内存的应用程序的性能。

为什么使用“大内存页”?

在虚拟内存管理中,内核维护一个将虚拟内存地址映射到物理地址的表,对于每个页面操作,内核都需要加载相关的映射。如果你的内存页很小,那么你需要加载的页就会很多,导致内核会加载更多的映射表。而这会降低性能。

使用“大内存页”,意味着所需要的页变少了。从而大大减少由内核加载的映射表的数量。这提高了内核级别的性能最终有利于应用程序的性能。

简而言之,通过启用“大内存页”,系统具只需要处理较少的页面映射表,从而减少访问/维护它们的开销!

如何配置“大内存页”?

运行下面命令来查看当前“大内存页”的详细内容。

root@kerneltalks # grep Huge /proc/meminfo
AnonHugePages:         0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

从上面输出可以看到,每个页的大小为 2MB(Hugepagesize),并且系统中目前有 0 个“大内存页”(HugePages_Total)。这里“大内存页”的大小可以从 2MB 增加到 1GB

运行下面的脚本可以知道系统当前需要多少个巨大页。该脚本取之于 Oracle。

#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk {'print $2'}`
# Start from 1 pages to be on the safe side and guarantee 1 free HugePage
NUM_PG=1
# Cumulative number of pages required to handle the running shared memory segments
for SEG_BYTES in `ipcs -m | awk {'print $5'} | grep "[0-9][0-9]*"`
do
   MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q`
   if [ $MIN_PG -gt 0 ]; then
      NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q`
   fi
done
# Finish with results
case $KERN in
   '2.4') HUGETLB_POOL=`echo "$NUM_PG*$HPG_SZ/1024" | bc -q`;
          echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
   '2.6' | '3.8' | '3.10' | '4.1' ) echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    *) echo "Unrecognized kernel version $KERN. Exiting." ;;
esac
# End

将它以 hugepages_settings.sh 为名保存到 /tmp 中,然后运行之:

root@kerneltalks # sh /tmp/hugepages_settings.sh
Recommended setting: vm.nr_hugepages = 124

你的输出类似如上结果,只是数字会有一些出入。

这意味着,你系统需要 124 个每个 2MB 的“大内存页”!若你设置页面大小为 4MB,则结果就变成了 62。你明白了吧?

配置内核中的“大内存页”

本文最后一部分内容是配置上面提到的 内核参数 ,然后重新加载。将下面内容添加到 /etc/sysctl.conf 中,然后输入 sysctl -p 命令重新加载配置。

vm.nr_hugepages=126

注意我们这里多加了两个额外的页,因为我们希望在实际需要的页面数量之外多一些额外的空闲页。

现在,内核已经配置好了,但是要让应用能够使用这些“大内存页”还需要提高内存的使用阀值。新的内存阀值应该为 126 个页 x 每个页 2 MB = 252 MB,也就是 258048 KB。

你需要编辑 /etc/security/limits.conf 中的如下配置:

soft memlock 258048
hard memlock 258048

某些情况下,这些设置是在指定应用的文件中配置的,比如 Oracle DB 就是在 /etc/security/limits.d/99-grid-oracle-limits.conf 中配置的。

这就完成了!你可能还需要重启应用来让应用来使用这些新的巨大页。

(LCTT 译注:此外原文有误,“透明大内存页”和“大内存页”不同,而且,在 Redhat 系统中,“大内存页” 不是默认启用的,而“透明大内存页”是启用的。因此这个段落删除了。)


via: https://kerneltalks.com/services/what-is-huge-pages-in-linux/

作者:Shrikant Lavhate 译者:lujun9972 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在学习了进程的 虚拟地址布局 之后,让我们回到内核,来学习它管理用户内存的机制。这里再次使用 Gonzo:

Linux kernel mm_struct

Linux 进程在内核中是作为进程描述符 task\_struct (LCTT 译注:它是在 Linux 中描述进程完整信息的一种数据结构)的实例来实现的。在 task\_struct 中的 mm 域指向到内存描述符mm\_struct 是一个程序在内存中的执行摘要。如上图所示,它保存了起始和结束内存段,进程使用的物理内存页面的 数量(RSS 常驻内存大小 Resident Set Size )、虚拟地址空间使用的 总数量、以及其它片断。 在内存描述符中,我们可以获悉它有两种管理内存的方式:虚拟内存区域集和页面表。Gonzo 的内存区域如下所示:

Kernel memory descriptor and memory areas

每个虚拟内存区域(VMA)是一个连续的虚拟地址范围;这些区域绝对不会重叠。一个 vm\_area\_struct 的实例完整地描述了一个内存区域,包括它的起始和结束地址,flags 决定了访问权限和行为,并且 vm\_file 域指定了映射到这个区域的文件(如果有的话)。(除了内存映射段的例外情况之外,)一个 VMA 是不能匿名映射文件的。上面的每个内存段(比如,堆、栈)都对应一个单个的 VMA。虽然它通常都使用在 x86 的机器上,但它并不是必需的。VMA 也不关心它们在哪个段中。

一个程序的 VMA 在内存描述符中是作为 mmap 域的一个链接列表保存的,以起始虚拟地址为序进行排列,并且在 mm\_rb 域中作为一个 红黑树 的根。红黑树允许内核通过给定的虚拟地址去快速搜索内存区域。在你读取文件 /proc/pid_of_process/maps 时,内核只是简单地读取每个进程的 VMA 的链接列表并显示它们

在 Windows 中,EPROCESS 块大致类似于一个 task\_struct 和 mm\_struct 的结合。在 Windows 中模拟一个 VMA 的是虚拟地址描述符,或称为 VAD;它保存在一个 AVL 树 中。你知道关于 Windows 和 Linux 之间最有趣的事情是什么吗?其实它们只有一点小差别。

4GB 虚拟地址空间被分配到页面中。在 32 位模式中的 x86 处理器中支持 4KB、2MB、以及 4MB 大小的页面。Linux 和 Windows 都使用大小为 4KB 的页面去映射用户的一部分虚拟地址空间。字节 0-4095 在页面 0 中,字节 4096-8191 在页面 1 中,依次类推。VMA 的大小 必须是页面大小的倍数 。下图是使用 4KB 大小页面的总数量为 3GB 的用户空间:

4KB Pages Virtual User Space

处理器通过查看页面表去转换一个虚拟内存地址到一个真实的物理内存地址。每个进程都有它自己的一组页面表;每当发生进程切换时,用户空间的页面表也同时切换。Linux 在内存描述符的 pgd 域中保存了一个指向进程的页面表的指针。对于每个虚拟页面,页面表中都有一个相应的页面表条目(PTE),在常规的 x86 页面表中,它是一个简单的如下所示的大小为 4 字节的记录:

x86 Page Table Entry (PTE) for 4KB page

Linux 通过函数去 读取设置 PTE 条目中的每个标志位。标志位 P 告诉处理器这个虚拟页面是否物理内存中。如果该位被清除(设置为 0),访问这个页面将触发一个页面故障。请记住,当这个标志位为 0 时,内核可以在剩余的域上做任何想做的事。R/W 标志位是读/写标志;如果被清除,这个页面将变成只读的。U/S 标志位表示用户/超级用户;如果被清除,这个页面将仅被内核访问。这些标志都是用于实现我们在前面看到的只读内存和内核空间保护。

标志位 D 和 A 用于标识页面是否是“脏的”或者是已被访问过。一个脏页面表示已经被写入,而一个被访问过的页面则表示有一个写入或者读取发生过。这两个标志位都是粘滞位:处理器只能设置它们,而清除则是由内核来完成的。最终,PTE 保存了这个页面相应的起始物理地址,它们按 4KB 进行整齐排列。这个看起来不起眼的域是一些痛苦的根源,因为它限制了物理内存最大为 4 GB。其它的 PTE 域留到下次再讲,因为它是涉及了物理地址扩展的知识。

由于在一个虚拟页面上的所有字节都共享一个 U/S 和 R/W 标志位,所以内存保护的最小单元是一个虚拟页面。但是,同一个物理内存可能被映射到不同的虚拟页面,这样就有可能会出现相同的物理内存出现不同的保护标志位的情况。请注意,在 PTE 中是看不到运行权限的。这就是为什么经典的 x86 页面上允许代码在栈上被执行的原因,这样会很容易导致挖掘出栈缓冲溢出漏洞(可能会通过使用 return-to-libc 和其它技术来找出非可执行栈)。由于 PTE 缺少禁止运行标志位说明了一个更广泛的事实:在 VMA 中的权限标志位有可能或可能不完全转换为硬件保护。内核只能做它能做到的,但是,最终的架构限制了它能做的事情。

虚拟内存不保存任何东西,它只是简单地 映射 一个程序的地址空间到底层的物理内存上。物理内存被当作一个称之为物理地址空间的巨大块而由处理器访问。虽然内存的操作涉及到某些总线,我们在这里先忽略它,并假设物理地址范围从 0 到可用的最大值按字节递增。物理地址空间被内核进一步分解为页面帧。处理器并不会关心帧的具体情况,这一点对内核也是至关重要的,因为,页面帧是物理内存管理的最小单元。Linux 和 Windows 在 32 位模式下都使用 4KB 大小的页面帧;下图是一个有 2 GB 内存的机器的例子:

Physical Address Space

在 Linux 上每个页面帧是被一个 描述符几个标志 来跟踪的。通过这些描述符和标志,实现了对机器上整个物理内存的跟踪;每个页面帧的具体状态是公开的。物理内存是通过使用 Buddy 内存分配 (LCTT 译注:一种内存分配算法)技术来管理的,因此,如果一个页面帧可以通过 Buddy 系统分配,那么它是未分配的(free)。一个被分配的页面帧可以是匿名的、持有程序数据的、或者它可能处于页面缓存中、持有数据保存在一个文件或者块设备中。还有其它的异形页面帧,但是这些异形页面帧现在已经不怎么使用了。Windows 有一个类似的页面帧号(Page Frame Number (PFN))数据库去跟踪物理内存。

我们把虚拟内存区域(VMA)、页面表条目(PTE),以及页面帧放在一起来理解它们是如何工作的。下面是一个用户堆的示例:

Physical Address Space

蓝色的矩形框表示在 VMA 范围内的页面,而箭头表示页面表条目映射页面到页面帧。一些缺少箭头的虚拟页面,表示它们对应的 PTE 的当前标志位被清除(置为 0)。这可能是因为这个页面从来没有被使用过,或者是它的内容已经被交换出去了。在这两种情况下,即便这些页面在 VMA 中,访问它们也将导致产生一个页面故障。对于这种 VMA 和页面表的不一致的情况,看上去似乎很奇怪,但是这种情况却经常发生。

一个 VMA 像一个在你的程序和内核之间的合约。你请求它做一些事情(分配内存、文件映射、等等),内核会回应“收到”,然后去创建或者更新相应的 VMA。 但是,它 并不立刻 去“兑现”对你的承诺,而是它会等待到发生一个页面故障时才去 真正 做这个工作。内核是个“懒惰的家伙”、“不诚实的人渣”;这就是虚拟内存的基本原理。它适用于大多数的情况,有一些类似情况和有一些意外的情况,但是,它是规则是,VMA 记录 约定的 内容,而 PTE 才反映这个“懒惰的内核” 真正做了什么。通过这两种数据结构共同来管理程序的内存;它们共同来完成解决页面故障、释放内存、从内存中交换出数据、等等。下图是内存分配的一个简单案例:

Example of demand paging and memory allocation

当程序通过 brk() 系统调用来请求一些内存时,内核只是简单地 更新 堆的 VMA 并给程序回复“已搞定”。而在这个时候并没有真正地分配页面帧,并且新的页面也没有映射到物理内存上。一旦程序尝试去访问这个页面时,处理器将发生页面故障,然后调用 do\_page\_fault()。这个函数将使用 find\_vma()搜索 发生页面故障的 VMA。如果找到了,然后在 VMA 上进行权限检查以防范恶意访问(读取或者写入)。如果没有合适的 VMA,也没有所尝试访问的内存的“合约”,将会给进程返回段故障。

找到了一个合适的 VMA,内核必须通过查找 PTE 的内容和 VMA 的类型去处理故障。在我们的案例中,PTE 显示这个页面是 不存在的。事实上,我们的 PTE 是全部空白的(全部都是 0),在 Linux 中这表示虚拟内存还没有被映射。由于这是匿名 VMA,我们有一个完全的 RAM 事务,它必须被 do\_anonymous\_page() 来处理,它分配页面帧,并且用一个 PTE 去映射故障虚拟页面到一个新分配的帧。

有时候,事情可能会有所不同。例如,对于被交换出内存的页面的 PTE,在当前(Present)标志位上是 0,但它并不是空白的。而是在交换位置仍有页面内容,它必须从磁盘上读取并且通过 do\_swap\_page() 来加载到一个被称为 major fault 的页面帧上。

这是我们通过探查内核的用户内存管理得出的前半部分的结论。在下一篇文章中,我们通过将文件加载到内存中,来构建一个完整的内存框架图,以及对性能的影响。


via: http://duartes.org/gustavo/blog/post/how-the-kernel-manages-your-memory/

作者:Gustavo Duarte 译者:qhwdw 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

在 Linux 系统上,有时你可能想从命令行快速地了解系统的已使用和未使用的内存空间。如果你是一个 Linux 新手,有个好消息:有一条系统内置的命令可以显示这些信息:free

在本文中,我们会讲到 free 命令的基本用法以及它所提供的一些重要的功能。文中提到的所有命令和用法都是在 Ubuntu 16.04LTS 上测试过的。

Linux free 命令

让我们看一下 free 命令的语法:

free [options]

free 命令的 man 手册如是说:

free 命令显示了系统的可用和已用的物理内存及交换内存的总量,以及内核用到的缓存空间。这些信息是从 /proc/meminfo 中得到的。

接下来我们用问答的方式了解一下 free 命令是怎么工作的。

Q1. 怎么用 free 命令查看已使用和未使用的内存?

这很容易,您只需不加任何参数地运行 free 这条命令就可以了:

free

这是 free 命令在我的系统上的输出:

view used and available memory using free command

这些列是什么意思呢?

  • total - 安装的内存的总量(等同于 /proc/meminfo 中的 MemTotalSwapTotal
  • used - 已使用的内存(计算公式为:used = total - free - buffers - cache
  • free - 未被使用的内存(等同于 /proc/meminfo 中的 MemFreeSwapFree
  • shared - 通常是临时文件系统使用的内存(等同于 /proc/meminfo 中的 Shmem;自内核 2.6.32 版本可用,不可用则显示为 0
  • buffers - 内核缓冲区使用的内存(等同于 /proc/meminfo 中的 Buffers
  • cache - 页面缓存和 Slab 分配机制使用的内存(等同于 /proc/meminfo 中的 CachedSlab
  • buff/cache - bufferscache 之和
  • available - 在不计算交换空间的情况下,预计可以被新启动的应用程序所使用的内存空间。与 cache 或者 free 部分不同,这一列把页面缓存计算在内,并且不是所有的可回收的 slab 内存都可以真正被回收,因为可能有被占用的部分。(等同于 /proc/meminfo 中的 MemAvailable;自内核 3.14 版本可用,自内核 2.6.27 版本开始模拟;在其他版本上这个值与 free 这一列相同)

Q2. 如何更改显示的单位呢?

如果需要的话,你可以更改内存的显示单位。比如说,想要内存以兆为单位显示,你可以用 -m 这个参数:

free -m

free command display metrics change

同样地,你可以用 -b 以字节显示、-k 以 KB 显示、-m 以 MB 显示、-g 以 GB 显示、--tera 以 TB 显示。

Q3. 怎么显示可读的结果呢?

free 命令提供了 -h 这个参数使输出转化为可读的格式。

free -h

用这个参数,free 命令会自己决定用什么单位显示内存的每个数值。例如:

diplsy data fromm free command in human readable form

Q4. 怎么让 free 命令以一定的时间间隔持续运行?

您可以用 -s 这个参数让 free 命令以一定的时间间隔持续地执行。您需要传递给命令行一个数字参数,做为这个时间间隔的秒数。

例如,使 free 命令每隔 3 秒执行一次:

free -s 3

如果您需要 free 命令只执行几次,您可以用 -c 这个参数指定执行的次数:

free -s 3 -c 5

上面这条命令可以确保 free 命令每隔 3 秒执行一次,总共执行 5 次。

注:这个功能目前在 Ubuntu 系统上还存在 问题,所以并未测试。

Q5. 怎么使 free 基于 1000 计算内存,而不是 1024?

如果您指定 free 用 MB 来显示内存(用 -m 参数),但又想基于 1000 来计算结果,可以用 --sj 这个参数来实现。下图展示了用与不用这个参数的结果:

How to make free use power of 1000 (not 1024) while displaying memory figures

Q6. 如何使 free 命令显示每一列的总和?

如果您想要 free 命令显示每一列的总和,你可以用 -t 这个参数。

free -t

如下图所示:

How to make free display total of columns

请注意 Total 这一行出现了。

总结

free 命令对于系统管理来讲是个极其有用的工具。它有很多参数可以定制化您的输出,易懂易用。我们在本文中也提到了很多有用的参数。练习完之后,请您移步至 man 手册了解更多内容。


via: https://www.howtoforge.com/linux-free-command/

作者:Himanshu Arora 译者:jessie-pang 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

用户可以在任何 Linux 操作系统的安装过程中或者是其它必要的时候创建交换空间。如果你在安装 Linux 的时候忘记了创建或是你想要再增加交换分区的空间,你随时都可以再创建或增加。

有时候在你安装后摇升级 RAM 的时候需要增加一点交换分区的空间,比如你要将你的系统的 RAM 从 1GB 升级到 2GB 你,那么你就不得不将你的交换分区空间也升级一下(从 2GB 到 4GB),这是因为它使用的容量是物理 RAM 的双倍容量。(LCTT 译注:其实这里是个误区,交换分区不一定非得是双倍的物理内存容量,只是惯例如此。事实上,如果你的物理内存足够的话,你完全可以不用交换分区——在这里的情形下,或许你增加了物理内存,就没必要增加交换分区大小了。)

交换空间是当物理内存(RAM 随机存取存储器)的用量已满时,被保留用作虚拟内存的磁盘上的空间。 如果系统在 RAM 满载时需要更多的内存资源,内存中的非活动页面将被移动到交换空间,这样可以帮助系统运行应用程序更多的时间,但不应该把它当做 RAM 的扩展。

建议你创建一个专用的交换分区,但是如果你没有可用的分区,那么可以使用交换文件,或交换分区和交换文件的组合。 交换空间通常建议用户至少 4 GB,用户也可以根据自己的要求和环境创建交换空间。

我发现大部分 VM 和 云服务器都没有交换分区,所以在这种情况下,我们可以使用以下三种方法创建,扩展或增加交换空间。

如何检测当前交换分区大小

通过 free & swapon 命令来检测当前的交换分区空间的大小。

$ free -h
              total        used        free      shared  buff/cache   available
Mem:           2.0G        1.3G        139M         45M        483M        426M
Swap:          2.0G        655M        1.4G

$ swapon --show
NAME      TYPE      SIZE   USED PRIO
/dev/sda5 partition   2G 655.2M   -1

上面的输出显示了当前的交换分区空间是 2GB

方法 1 : 通过 fallocate 命令创建交换文件

fallocate 程序是立即创建预分配大小的文件的最佳方法。

下面这个命令会创建一个 1GB 大小 的 /swapfile

$ sudo fallocate -l 1G /swapfile

检查一下创建的文件的大小是否正确。

$ ls -lh /swapfile
-rw-r--r-- 1 root root 1.0G Jun  7 09:49 /swapfile

将该文件的权限设置为 600 这样只有 root 用户可以访问这个文件。

$ sudo chmod 600 /swapfile

通过运行以下的命令来将此文件转换为交换文件。

$ sudo mkswap /swapfile
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=cda50e0e-41f3-49c7-af61-b8cb4a33a464

通过运行以下的命令来使交换文件生效。

$ sudo swapon /swapfile

将新创建的交换文件添加到 fstab 文件中,这样交换分区空间的修改即使在重启后也可以生效。

$ vi /etc/fstab

/swapfile  swap  swap  defaults  0 0

检查一下新创建的交换文件。

$ swapon --show
NAME      TYPE       SIZE   USED PRIO
/dev/sda5 partition    2G 657.8M   -1
/swapfile file      1024M     0B   -2

现在我可以看到一个新的 1GB 的 /swapfile1 文件了。重启系统以使新的交换文件生效。

方法 2 : 通过 dd 命令来创建交换文件

dd 命令是另一个实用程序,可以帮助我们立即创建预分配大小的文件。

以下 dd 命令将创建 1GB 的 /swapfile1

$ sudo dd if=/dev/zero of=/swapfile1 bs=1G count=1
1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 16.6154 s, 64.6 MB/s

详解:

  • if=/dev/zero 是输入文件,/dev/zero 是类 Unix 操作系统中的一个特殊文件,它提供从它读取的尽可能多的空字符(ASCII NUL,0x00)。
  • of=/swapfile1 设置输出文件。
  • bs=1G 一次性读写的大小为 1GB
  • count=1 仅复制一个输入块

检查一下创建的文件的大小是否正确。

$ ls -lh /swapfile1
-rw-r--r-- 1 root root 1.0G Jun  7 09:58 /swapfile1

将该文件的权限设置为 600 这样只有 root 用户可以访问这个文件。

$ sudo chmod 600 /swapfile1

通过运行以下的命令来将此文件转换为交换文件。

$ sudo mkswap /swapfile1
Setting up swapspace version 1, size = 1024 MiB (1073737728 bytes)
no label, UUID=96def6d7-b2da-4954-aa72-aa32316ec993

通过运行以下的命令来使交换文件生效。

$ sudo swapon /swapfile1

将新创建的交换文件添加到 fstab 文件中,这样交换分区空间的修改即使在重启后也可以生效。

$ vi /etc/fstab

/swapfile1  swap  swap  defaults  0 0

检查新创建的交换文件。

$ swapon --show
NAME       TYPE       SIZE USED PRIO
/dev/sda5  partition    2G 1.3G   -1
/swapfile  file      1024M   0B   -2
/swapfile1 file      1024M   0B   -3

现在我可以看到一个新的 1GB 的 /swapfile1 了。重启系统以使新的交换文件生效。

方法 3 : 通过硬盘分区来创建交换文件

我们也推荐使用通过硬盘分区的方式来创建交换分区。

如果你已经在你的另一个硬盘上通过 fdisk 命令创建了一个新的分区,假设我们已经创建了一个叫做 /dev/sda4 的分区。

使用 mkswap 命令来将这个分区转换成交换分区。

$ sudo mkswap /dev/sda4

通过运行以下命令来使交换文件生效。

$ sudo swapon /dev/sda4

把新增的交换文件添加到 fstab 文件中,这样即使是重启了系统交换分区的修改也能生效。

$ vi /etc/fstab

/dev/sda4  swap  swap  defaults  0 0

检查新创建的交换文件。

$ swapon --show
NAME       TYPE       SIZE USED PRIO
/dev/sda5  partition    2G 1.3G   -1
/swapfile  file      1024M   0B   -2
/swapfile1 file      1024M   0B   -3
/dev/sda4  partition    1G   0B   -4

我可以看到新的交换分区 1GB 的 /dev/sda4。重启系统就可以使用新的交换分区了。

(题图:Pixabay,CC0)


via: http://www.2daygeek.com/add-extend-increase-swap-space-memory-file-partition-linux/

作者:2DAYGEEK 译者:chenxinlong 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出