• Linux学习-44-虚拟内存、物理内存和swap分区的作用


    10.12 Linux虚拟内存和物理内存
    • 直接从内存读写数据要比从硬盘读写数据快得多,因此更希望所有数据的读取和写入都在内存中完成,然而内存是有限的,这样就引出了物理内存与虚拟内存的概念。物理内存就是系统硬件提供的内存大小,是真正的内存。相对于物理内存,在 Linux 下还有一个虚拟内存的概念,虚拟内存是为了满足物理内存的不足而提出的策略,它是利用磁盘空间虚拟出的一块逻辑内存。用作虚拟内存的磁盘空间被称为交换空间(又称 swap 空间)。

    • 作为物理内存的扩展,Linux 会在物理内存不足时,使用交换分区的虚拟内存,更详细地说,就是内核会将暂时不用的内存块信息写到交换空间,这样一来,物理内存得到了释放,这块内存就可以用于其他目的,当需要用到原始的内容时,这些信息会被重新从交换空间读入物理内存。Linux 的内存管理采取的是分页存取机制,为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。

    • 要深入了解 Linux 内存运行机制,需要知道下面提到的几个方面:

      • 首先,Linux 系统会不时地进行页面交换操作,以保持尽可能多的空闲物理内存,即使并没有什么事情需要内存,Linux 也会交换出暂时不用的内存页面,因为这样可以大大节省等待交换所需的时间。
      • 其次,Linux 进行页面交换是有条件的,不是所有页面在不用时都交换到虚拟内存,Linux 内核根据“最近最经常使用”算法,仅仅将一些不经常使用的页面文件交换到虚拟内存。
    • 有时候Linux 物理内存还有很多,但是交换空间也使用了很多,其实这并不奇怪。例如,一个占用很大内存的进程运行时,需要耗费很多内存资源,此时就会有一些不常用页面文件被交换到虚拟内存中,但后来这个占用很多内存资源的进程结束并释放了很多内存时,刚才被交换出去的页面文件并不会自动交换进物理内存(除非有这个必要),那么此时系统物理内存就会空闲很多,同时交换空间也在被使用,就出现了刚才所说的现象了。

    • 最后,交换空间的页面在使用时会首先被交换到物理内存,如果此时没有足够的物理内存来容纳这些页面,它们又会被马上交换出去,如此一来,虚拟内存中可能没有足够的空间来存储这些交换页面,最终会导致 Linux 出现假死机、服务异常等问题。Linux 虽然可以在一段时间内自行恢复,但是恢复后的系统己经基本不可用了。

    • 因此,合理规划和设计 Linux 内存的使用是非常重要的,关于物理内存和交换空间的大小设置问题,取决于实际所用的硬盘大小,但大致遵循这样一个基本原则:

      1. 如果内存较小(根据经验,物理内存小于 4GB),一般设置 swap 分区大小为内存的 2 倍;
      2. 如果物理内存大于 4GB,而小于 16GB,可以设置 swap 分区大小等于物理内存;
      3. 如果内存大小在 16GB 以上,可以设置 swap 为 0,但并不建议这么做,因为设置一定大小的 swap 分区是有一定作用的。
    10.13 Linux swap分区及作用详解
    • 在安装系统的时候已经建立了 swap 分区。swap 分区通常被称为交换分区,这是一块特殊的硬盘空间,即当实际内存不够用的时候,操作系统会从内存中取出一部分暂时不用的数据,放在交换分区中,从而为当前运行的程序腾出足够的内存空间。也就是说,当内存不够用时,我们使用 swap 分区来临时顶替。这种“方式应用于几乎所有的操作系统中。
    • 使用 swap 交换分区,显著的优点是,通过操作系统的调度,应用程序实际可以使用的内存空间将远远超过系统的物理内存。由于硬盘空间的价格远比 RAM 要低,因此这种方式无疑是经济实惠的。当然,频繁地读写硬盘,会显著降低操作系统的运行速率,这也是使用 swap 交换分区最大的限制。

    相比较而言,Windows 不会为 swap 单独划分一个分区,而是使用分页文件实现相同的功能,在概念上,Windows 称其为虚拟内存,从某种意义上将,这个叫法更容易理解。因此,初学者将 swap 交换分区理解为虚拟内存是没有任何问题的。

    • 具体使用多大的 swap 分区,取决于物理内存大小和硬盘的容量。一般来讲,swap 分区容量应大于物理内存大小,建议是内存的两倍,但不超过 2GB。但是,有时服务器的访问量确实很大,有可能出现 swap 分区不够用的情况,所以我们需要学习 swap 分区的构建方法。

    • 建立新的 swap 分区,只需要执行以下几个步骤。

      1. 分区:不管是 fdisk 命令还是 parted 命令,都需要先区。
      2. 格式化:格式化命令稍有不同,使用 mkswap 命令把分区格式化成 swap 分区。
      3. 使用 swap 分区。
    • 分区:仍以 /dev/sdb 分区作为实验对象。不过,如果分区刚刚使用 parted 命令转变为 GPT 分区表,则记得转换回 MBR 分区表,fdisk 命令才能识别,否则干脆新添加一块硬盘做实验。

    [root@CncLucZK ~]# fdisk /dev/sdb
    #以/dev/sdb分区为例
    WARNING: DOS-compatible mode is deprecated.It's strongly recommended to switch off the mode (command 'c') and change display units to sectors (command 'u').
    Command (m for help): n
    #新建
    Command action e extended p primary partition (1-4)
    P
    #主分区
    Partition number (1-4): 1
    #分区编号
    First cylinder (1-2610, default 1):
    #起始柱面
    Using default value 1
    Last cylinder, +cylinders or +size{K, M, G} (1-2610, default 2610): +500M
    #大小
    Command (m for help): p
    #查看一下
    Disk /dev/sdb: 21.5GB, 21474836480 bytes
    255 heads, 63 sectors/track, 2610 cylinders
    Units = cylinders of 16065 *512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes 1512 bytes
    Disk identifier: OxOOOOOebd
    Device Boot Start End Blocks Id System
    /dev/sdb1 1 65 522081 83 Linux
    #刚分配的分区ID是83,是Linux分区,我们在这里要分配swap分区
    Command (m for help): t
    #修改分区的系统ID
    Selected partition 1
    #只有一个分区,所以不用选择分区了
    Hex code (type L to list codes): 82
    #改为swap分区的ID
    Changed system type of partition 1 to 82 (Linux swap / Solaris)
    Command (m for help): p
    #再查看一下
    Disk /dev/sdb: 21.5 GB, 21474836480 bytes
    255 heads, 63 sectors/track, 2610 cylinders
    Units = cylinders of 16065 *512 = 8225280 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes 1512 bytes Disk identifier: OxOOOOOebd
    Device Boot Start End Blocks Id System
    /dev/sdb1 1 65 522081 82 Linux swap / Solaris
    #修改过来了
    Command (m for help): w
    #记得保存退出
    The partition table has been altered!
    Calling ioctl() to re-read partition table.
    Syncing disks.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 格式化成 swap 分区,所以格式化命令是 mkswap
    [root@CncLucZK ~]# mkswap /dev/sdb1
    Setting up swapspace version 1, size = 522076 KiB
    no label, UUID=c3351 dc3-f403-419a-9666-c24615e170fb
    
    • 1
    • 2
    • 3
    • 在使用 swap 分区之前,了解下free 命令。命令如下:
    [root@CncLucZK ~]#free
    total used free shared buffers cached	available		
    Mem: 1030796 130792 900004 0 15292 55420
    -/+ buffers/cache: 60080 970716
    Swap: 2047992 0 2047992
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • free 命令主要是用来查看内存和 swap 分区的使用情况的,其中:
      • total:是指总数;
      • used:是指已经使用的;
      • free:是指空闲的;
      • shared:是指共享的;
      • buffers:是指缓冲内存数;
      • cached:是指缓存内存数,单位是KB;

    buffers(缓冲)和 cached(缓存)的区别。简单来讲,cached 是给读取数据时加速的,buffers 是给写入数据加速的。cached 是指把读取出来的数据保存在内存中,当再次读取时,不用读取硬盘而直接从内存中读取,加速了数据的读取过程;buffers 是指在写入数据时,先把分散的写入操作保存到内存中,当达到一定程度后再集中写入硬盘,减少了磁盘碎片和硬盘的反复寻道,加速了数据的写入过程。

    • 我们已经看到,在加载进新的 swap 分区之前,swap 分区的大小是 2000MB,接下来只要加入 swap 分区就可以了,使用命令 swapon。命令格式如下:
    [root@CncLucZK ~]# swapon 分区设备文件名
    #将新的 swap 分区sdb1加入到现在的swap 分区
    [root@localhost ~]# swapon /dev/sdb1
    #swap分区已加入,我们查看一下。
    [root@localhost ~]#free							#或查看cat /proc/swaps
    total used free shared buffers cached
    Mem: 1030796 131264 899532 0 15520 55500
    -/+ buffers/cache: 60244 970552
    Swap: 2570064 0 2570064
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • swap 分区的大小变成了 2500MB,加载成功了。如果要取消新加入的 swap 分区,则也很简单,命令如下:

    • 如果想让 swap 分区开机之后自动挂载,就需要修改 /etc/fstab 文件,命令如下:

    [root@CncLucZK ~]#vi /etc/fstab
    UUID=c2ca6f57-b15c-43ea-bca0-f239083d8bd2 / ext4 defaults 1 1
    UUID=0b23d315-33a7-48a4-bd37-9248e5c443451 boot ext4 defaults 1 2
    UUID=4021be19-2751-4dd2-98cc-383368c39edb swap swap defaults 0 0
    tmpfs /dev/shm
    tmpfs defaults 0 0
    devpts /dev/pts
    devpts gid=5, mode=620 0 0
    sysfs /sys
    sysfs defaults 0 0
    proc /proc
    proc defaults 0 0
    /dev/sdb1 swap swap
    defaults 0 0
    #加入新swap分区的相关内容,这里直接使用分区的设备文件名,也可以使用UUID。
    #blkid /dev/sdb1查找设备的UUID
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • swap作用实践:在以源码包安装文件时,因为内存不够导致编译安装make install失败,可以先使用交换分区来解决,编译安装后再删除掉即可。
    报错:cc: internal compiler error: Killed (program cc1)
    
    • 1
    #处理方式
    sudo dd if=/dev/zero of=/swapfile bs=64M count=16		#创建了一个64M的交换文件/swapfile
    sudo mkswap /swapfile									#在一个文件或者设备上建立交换分区
    sudo swapon /swapfile									#将/swapfile加入到现有分区中,启用交换分区 
    #取消交换分区:
    sudo swapoff /swapfile									#删除交换空间,禁用交换分区
    sudo rm /swapfile										#移除文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    参考文献:
    Linux虚拟内存和物理内存
    Linux swap分区及作用详解
    Linux 磁盘管理

    下一篇:Linux学习-45-高级文件系统管理-磁盘配额
  • 相关阅读:
    python爬虫实战:获取电子邮件和联系人信息
    结构体数组经典运用---选票系统
    springboot + solr
    记录mysql ON DUPLICATE KEY UPDATE 时的小坑以及其底层处理逻辑
    持续集成(CICD)- gogs仓库的部署和使用
    工欲善其事,必先利其器,五款实用的办公软件推荐
    【vue3】Transition过渡组件
    -2 Hello World 小案例
    Meilisearch客户端完美改造
    C++的在vs上面用ffmpeg做音频流捕捉的代码
  • 原文地址:https://blog.csdn.net/weixin_42045639/article/details/127897428