一、内存的基本概念
内存(Memory):是程序运行的场所,所有进程(执行的程序)都必须占用一定数量的内存,它有时候是用来存放从磁盘载入的程序代码,有时候是存放用户输入的中间数据、参数等。
Linux系统内存管理的职责是:进程请求内存时分配可用内存,进程释放内存时回收内存,跟踪系统内存的使用情况。
二、物理内存和虚拟内存
物理内存就是系统硬件的内存大小,是系统真正的内存。
相对于物理内存而言,在 Linux 系统下还有虚拟内存,所谓的虚拟内存就是为了满足物理内存的不足而提出的策略。虚拟内存就是利用磁盘空间虚拟出的一块逻辑内存,用作虚拟内存的磁盘空间被称为交换空间(swap space)。
虚拟内存是物理内存的扩展,当系统中的物理内存不足时,就会使用交换分区的虚拟内存。内核会把系统中暂时不需要的内存块信息存储到交换空间,从而释放了物理内存,因此物理内存可以作用于其他地方,当需要使用到原始的内容时,这些信息会被重新从交换空间读入物理内存。
三、内存管理常用方法
1.调页算法是将内存中最近不经常使用的页面交换到磁盘上,把经常使用的页面保留在内存中供进程使用。
2.交换技术是系统将整个进程,全部交换到磁盘上,注意不是部分页面。正常情况下,系统会发生一些交换过程。
当物理内存严重不足时,系统会频繁使用调页和交换,虽然使用虚拟内存扩大了内存的容量,但却增加了磁盘 I/O 的负载。进一步降低了系统对作业的执行速度,即系统 I/O 资源问题又会影响到内存资源的分配。
ps:对于 Linux 系统的内存管理,通常采用的是分页存取机制。为了保证物理内存能得到充分的利用,内核会在适当的时候将物理内存中不经常使用的数据块自动交换到虚拟内存中,而将经常使用的信息保留到物理内存。
四、物理内存地址与虚拟内存地址
计算机对虚拟内存地址空间(32 位为 4GB)进行分页,产生页(page);对物理内存地址空间进行分页,产生页帧(page frame)。页和页帧的大小相同,但虚拟内存页的个数必须要大于物理内存页帧的个数。
另外在计算机上还有一个页表(page table),主要用来映射虚拟内存页到物理内存页,即是页号到页帧号的映射,而且是一对一的映射。
在将应用程序加载到内存空间执行时,操作系统负责代码段、数据段和 BSS 段的加载,并在内存中为这些段分配空间。栈也由操作系统分配和管理;堆由程序员自己管理,即显式地申请和释放空间。BSS段、数据段和代码段是可执行程序编译时的分段,运行时还需要栈和堆。该过程的特点如下:
1.每个进程都有自己独立的 4GB 内存空间,各个进程的内存空间具有类似的结构;
2.每个进程的 4GB 内存空间都只是虚拟的内存空间,每次访问内存空间的某个地址时,都需要把地址翻译为实际物理内存地址;
3.所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上;
4.一般认为虚拟空间全部被映射到了磁盘空间中,并且由页表记录映射位置。
五、交换空间的使用
Linux 系统会有频繁的页面交换操作,这样是为了让更多的物理空间保持空闲,即使现在不需要内存,Linux 系统也会交换出暂时不需要使用的内存页面以减少等待交换所需的时间。
Linux 系统在进行页面交换时是有条件的。不是所有的页面在不使用时都能够交换到虚拟内存中,Linux 内核根据“最近最经常使用”算法,只将一些不经常使用的页面文件交换到虚拟内存,这可能会出现 Linux 物理内存还有很多,但是交换空间也使用了很多的现象。
这是因为当一个需要占用很大内存的进程在运行时,需要耗费很多的内存资源,此时就会有一些不常用的页面文件被交换到虚拟内存中;最后当这个占用很多内存资源的进程结束并且释放了较多的内存时,被交换出去的页面文件并不会自动交换到物理内存,此时系统的物理内存就会空闲很多,但交换空间还处于正在被使用的状态。
交换空间的页面在使用时会最先被交换到物理内存,如果此时没有足够的物理内存来存放这些页面,那么这些页面又会被交换出去。因此,虚拟内存中可能没有足够的空间来存放这些交换页面,最终会导致 Linux 出现假死机、服务异常等问题,Linux 系统虽然可以在一段时间内自动恢复,但是恢复后的系统已经基本上不能使用了。
1.交换空间的大小
当 Linux 系统中的物理内存很大时,可能没有交换空间系统也能很好地运行。但当物理内存使用完时,系统就会崩溃,因为它没有可以释放内存的方式,因此在系统中提供一个交换空间也是很有必要的。那么交换空间通常多大合适呢?
2.交换空间的分配
对于桌面系统而言,使用系统内存的两倍的交换空间,就可以运行大量的应用程序,使更多的 RAM 用于主要的应用。
对于服务器而言,使用小量的交换空间(通常是物理内存的一半),这样就可以通过监控交换空间的大小来预警是否需要增加 RAM 的大小。
对于老式台式机而言,则需要使用尽可能大的交换空间。
六、关闭系统交换区-swapoff
1.含义
swapoff实际上为swapon的符号连接,可用来关闭系统的交换区
语法格式:swapoff [参数]
2.常用参数:
-a |
将/etc/fstab文件中所有设置为swap的设备关闭 |
-h |
帮助信息 |
-V |
版本信息 |
3.关闭交换分区
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 133 1625 9 221 1672
Swap: 2047 0 2047
[root@jindada ~]# swapoff -a
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 132 1627 9 220 1673
Swap: 0 0 0
七、激活交换空间-swapon
1.含义
swapon命令用于激活Linux系统中交换空间,Linux系统的内存管理必须使用交换区来建立虚拟内存。
语法格式: swapon [参数 ]
2.常用参数
-a |
将/etc/fstab文件中所有设置为swap的设备,启动为交换区 |
-h |
显示帮助 |
-p |
制定交换区的优先顺序 |
-s |
显示交换区的使用情况 |
3.常见示例
显示交换区的版本信息
[root@jindada ~]# swapon -v /dev/hdb4
显示交换区的使用情况
[root@jindada ~]# swapon -s
设定优先权
[root@jindada ~]# swapon -p 3 /dev/hdb4
自动启动所有SWAP装置
[root@jindada ~]# swapon -a
显示swap命令的帮助文档
[root@jindada ~]# swapon -h
八、建立和设置交换分区-mkswap
1.含义
mkswap命令用于在一个文件或者设备上建立交换分区。在建立完之后要使用sawpon命令开始使用这个交换区。最后一个选择性参数指定了交换区的大小,但是这个参数是为了向后兼容设置的,没有使用的必要,一般都将整个文件或者设备作为交换区。
语法格式:mkswap [参数]
2.常用参数
-c |
建立交换区前,先检查是否有损坏的区块 |
-f |
在SPARC电脑上建立交换区,要加此参数 |
-v0 |
建立旧式交换区,此为预设值 |
-v1 |
建立新式交换区 |
3.常见示例
添加交换分区,假设存在并设置 /dev/sdb3为交换分区
[root@jindada ~]# mkswap /dev/sdb2
[root@jindada ~]# swapon /dev/sdb2
用dd创建一个512M的交换文件,将文件设置为交换分区
[root@jindada ~]# dd if=/dev/zero of=/swapfile1 bs=1024 count=524288
[root@jindada ~]# mkswap /swapfile1
[root@jindada ~]# swapon /swapfile1
九、重读分区表-partprobe
1.含义
partprobe命令用于重读分区表,将磁盘分区表变化信息通知内核,请求操作系统重新加载分区表。如果删除文件后,仍然提示占用空间,可以用partprobe在不重启的情况下重读分区 。
语法格式:partprobe [参数]
2.常用参数
-d |
不更新内核 |
-s |
显示摘要和分区 |
-h |
显示帮助信息 |
-v |
显示版本信息 |
3.常见示例
在安装Linux系统之后,创建分区并且在不重新启动机器的情况下让系统识别这些分区(sdb6为新创建的分区):
[root@jindada ~]# partprobe /dev/sdb6
十、综合案例
1.添加一个swap分区
#1.创建一个1G的分区
[root@jindada ~]# fdisk /dev/sdb
Welcome to fdisk (util-linux 2.23.2).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.
Command (m for help): n
Partition type:
p primary (1 primary, 1 extended, 2 free)
l logical (numbered from 5)
Select (default p): p
Partition number (3,4, default 3):
First sector (125831168-209715199, default 125831168):
Using default value 125831168
Last sector, +sectors or +size{K,M,G} (125831168-209715199, default 209715199): +1G
Partition 3 of type Linux and of size 1 GiB is set
Command (m for help): p
Disk /dev/sdb: 107.4 GB, 107374182400 bytes, 209715200 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk label type: dos
Disk identifier: 0x5b8d3e75
Device Boot Start End Blocks Id System
/dev/sdb1 2048 20973567 10485760 83 Linux
/dev/sdb2 20973568 125831167 52428800 5 Extended
/dev/sdb3 125831168 127928319 1048576 83 Linux
/dev/sdb5 20975616 62918655 20971520 83 Linux
Command (m for help): w
The partition table has been altered!
Calling ioctl() to re-read partition table.
WARNING: Re-reading the partition table failed with error 16: Device or resource busy.
The kernel still uses the old table. The new table will be used at
the next reboot or after you run partprobe(8) or kpartx(8)
Syncing disks.
#2.重读分区表
[root@jindada ~]# partprobe #通知内核,系统分区表发生变化
#3.将这个分区变为swap分区
[root@jindada ~]# mkswap /dev/sdb3
Setting up swapspace version 1, size = 1048572 KiB
no label, UUID=8a9c926b-de0d-4b49-bcb8-39a9c0b834a8
#4.把这个分区加入到swap
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 77 1819 0 84 1774
Swap: 2047 69 1978
[root@jindada ~]# swapon -s
Filename Type Size Used Priority
/dev/sda2 partition 2097148 71168 -2
[root@jindada ~]# swapon /dev/sdb3
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 78 1818 0 84 1773
Swap: 3071 69 3002
[root@jindada ~]# swapon -s
Filename Type Size Used Priority
/dev/sda2 partition 2097148 70912 -2
/dev/sdb3 partition 1048572 0 -3
2.移除和禁用swap
#1.移除swap
[root@jindada ~]# swapoff /dev/sdb3
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 78 1818 0 84 1773
Swap: 2047 69 1978
#2.禁用swap
[root@jindada ~]# swapoff -a
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 128 1759 9 92 1715
Swap: 0 0 0
3.启用swap
[root@jindada ~]# swapon -a
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 129 1758 9 92 1713
Swap: 2047 0 2047
4.生成一个大文件 ,作为swap
[root@jindada ~]# dd if=/dev/zero of=/root/swap.txt bs=100M count=10
10+0 records in
10+0 records out
1048576000 bytes (1.0 GB) copied, 8.33166 s, 126 MB/s
[root@jindada ~]# ll
total 1024000
-rw-r--r-- 1 root root 1048576000 Aug 3 11:21 swap.txt
[root@jindada ~]# mkswap swap.txt
Setting up swapspace version 1, size = 1023996 KiB
no label, UUID=51e07b8a-971a-47ec-972e-36f8273ec3cd
[root@jindada ~]# ll
total 1024000
-rw-r--r-- 1 root root 1048576000 Aug 3 11:22 swap.txt
[root@jindada ~]# file swap.txt
swap.txt: Linux/i386 swap file (new style), version 1 (4K pages), size 255999 pages, no label, UUID=51e07b8a-971a-47ec-972e-36f8273ec3cd
5.修改文件权限
[root@jindada ~]# chmod 600 swap.txt
6.开启swap并验证
#1.开启swap
[root@jindada ~]# swapon /root/swap.txt
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 132 727 9 1120 1663
Swap: 3047 0 3047
#2.关闭swap
[root@jindada ~]# swapoff swap.txt
[root@jindada ~]# free -m
total used free shared buff/cache available
Mem: 1980 130 729 9 1120 1665
Swap: 2047 0 2047