Swap意思是交换分区,通常我们说的虚拟内存,是从硬盘中划分出的一个分区。当物理内存不够用的时候,内核就会释放缓存区(buffers/cache)里一些长时间不用的程序,然后将这些程序临时放到Swap中,也就是说如果物理内存和缓存区内存不够用的时候,才会用到Swap。虚拟内存并不是等到物理内存用尽了才使用的,是否尽量的使用或不使用swap,在内核空间有一个参数控制。
1
2
3
|
[root@justin ~]
# cat /proc/sys/vm/swappiness
60
[root@justin ~]
#
|
swappiness=0 的时候表示最大限度使用物理内存,然后才是swap空间;
swappiness=100 的时候表示积极的使用swap分区,并且把内存上的数据及时的搬运到swap空间里面。
通过修改swappiness值来决定swap和物理内存使用情况
当达到这个值时,系统会将内存中不经常调用、CPU不经常处理的数据转移到交换分区中,以腾出更多的内存空间让常用的程序使用。Red Hat(红帽官方)推荐交换分区的大小应当与系统物理内存的大小保持线性比例关系。不过在小于2GB物理内存的系统中,交换分区大小应该设置为内存大小的 两倍,如果内存大小多于2GB,交换分区大小应该是物理内存大小加上2GB。其原因在于,系统中的物理内存越大, 对于内存的负荷可能也越大。在32位的Linux系统中,每一个交换分区空间最大不能超过2GB,而且同时启用的交换分区数量最多只能有32个。64位系统没有这个限制。
配置交换分区空间也就是要指定用哪个分区作为交换分区。在用fdisk命令进行分区时,所有的分区默认使用的文件系统类型为EXT4,如果要将某个分区作为交换分区,则首先必须更改该分区的类型。
在fdisk命令中,使用“t”指令可以更改分区的类型,只要依次指定分区序号及更改后分区类型ID标记号即可。如果不知道分区类型对应的ID号,可以输入“l”指令查看各种分区类型所对应的ID标记号
1
2
3
4
5
6
7
8
9
10
|
Command (m
for
help): l
0 Empty 24 NEC DOS 81 Minix / old Lin bf Solaris
1 FAT12 39 Plan 9 82 Linux swap / So c1 DRDOS
/sec
(FAT-
2 XENIX root 3c PartitionMagic 83 Linux c4 DRDOS
/sec
(FAT-
3 XENIX usr 40 Venix 80286 84 OS
/2
hidden C: c6 DRDOS
/sec
(FAT-
4 FAT16 <32M 41 PPC PReP Boot 85 Linux extended c7 Syrinx
5 Extended 42 SFS 86 NTFS volume
set
da Non-FS data
6 FAT16 4d QNX4.x 87 NTFS volume
set
db CP
/M
/ CTOS / .
7 HPFS
/NTFS
4e QNX4.x 2nd part 88 Linux plaintext de Dell Utility
8 AIX 4f QNX4.x 3rd part 8e Linux LVM
df
BootIt
|
Linux系统中最常用的两种文件系统EXT4的ID标记号为83、swap的ID标记号为82(十六进制数)
格式化成专门的swap文件系统不能使用先前的mkfs格式化命令,要创建交换文件系统,必须使用专门的mkswap命令
total | used | free | shared | buffers | cached | |
Mem(物理机上内存状况) | 总内存 | 已用内存 | 未用内存 | 共享的内存 | 用于缓冲的(通常是为了写操作设定的) | 用于缓存的(通常是为了读操作设定的) |
-/+ buffers/cache | 表示真正意义上的已用内存空间大小(减去缓存缓冲) | 表示真正意义上的未用空间(加上缓存缓冲) | ||||
Swap(交换分区大小及使用状况) |
上图可以看出,总内容8G,使用内容并不是1993648、空闲内存也并不是6068256,因为有了缓存机制,第一行的used包含了系统使用的buffer及cache,而free则没包含buffer及cache,这部分也是可以使用的部分。具体算法如下:
空闲内存=free(6068256)+buffers(224516)+cached(790588)
已用内存=total(8061904 )-空闲内存
由此算出空闲内存是7083360M,已用内存978544M,这才是真正的使用率,系统的可用内存可以参考第二行-/+ buffers/cache数据数据
缓存机制介绍
在Linux系统中,为了提高文件系统性能,内核利用一部分物理内存分配出缓冲区,用于缓存系统操作和数据文件,当内核收到读写的请求时,内核先去缓存区找是否有请求的数据,有就直接返回,如果没有则通过驱动程序直接操作磁盘。内核在保证系统能正常使用物理内存和数据量读写情况下来分配缓冲区大小。
缓存机制优点:减少系统调用次数,降低CPU上下文切换和磁盘访问频率。
CPU上下文切换:CPU给每个进程一定的服务时间,当时间片用完后,内核从正在运行的进程中收回处理器,同时把进程当前运行状态保存下来,然后加载下一个任务,这个过程叫做上下文切换。实质上就是被终止运行进程与待运行进程的进程切换。
buffer与cache的差别:
A buffer is something that has yet to be "written" to disk.
A cache is something that has been "read" from the disk and stored for later use.
buffer:
用来缓存metadata及pages,可以理解为系统缓存,例如,vi打开一个文件。
缓冲区,一个用于存储速度不同步的设备或优先级不同的设备之间传输数据的区域。通过缓冲区,可以使进程之间的相互等待变少,从而使从速度慢的设备读入数据时,速度快的设备的操作进程不发生间断。
cache:
用来给文件做缓存,可以理解为数据块缓存,例如,dd if=/dev/zero of=/tmp/test count=1 bs=1G 测试写入一个文件,就会被缓存到缓冲区中,当下一次再执行这个测试命令时,写入速度会明显很快。
高速缓存,是位于CPU与主内存间的一种容量较小但速度很高的存储器。由于CPU的速度远高于主内存,CPU直接从内存中存取数据要等待一定时间周期, Cache中保存着CPU刚用过或循环使用的一部分数据,当CPU再次使用该部分数据时可从Cache中直接调用,这样就减少了CPU的等待时间,提高了系统的效率。Cache又分为一级Cache(L1 Cache)和二级Cache(L2 Cache),L1 Cache集成在CPU内部,L2 Cache早期一般是焊在主板上,现在也都集成在CPU内部,常见的容量有256KB或512KB L2 Cache。
当你读写文件的时候,Linux内核为了提高读写性能与速度,会将文件在内存中进行缓存,
这部分内存就是Cache Memory(缓存内存)。即使你的程序运行结束后,Cache Memory也不会
自动释放。这就会导致你在Linux系统中程序频繁读写文件后,你会发现可用物理内存会很少。
其实这缓存内存(Cache Memory)在你需要使用内存的时候会自动释放,所以你不必担心没有
内存可用。
swap清理:
1
|
swapoff -a && swapon -a
|
这样清理有个前提条件,空闲的内存必须比已经使用的swap空间大
释放缓存区内存的方法
临时修改:
清理pagecache(页面缓存)
1
2
3
4
5
6
|
[root@localhost ~]
# cat /proc/sys/vm/drop_caches
0
[root@localhost ~]
# echo 1 > /proc/sys/vm/drop_caches
[root@localhost ~]
# cat /proc/sys/vm/drop_caches
1
[root@localhost ~]
#
|
清理dentries(目录缓存)和inodes
1
|
[root@localhost ~]
# echo 2 > /proc/sys/vm/drop_caches
|
清理pagecache、dentries和inodes
1
2
3
4
5
|
[root@localhost ~]
# sysctl -w vm.drop_caches=3
vm.drop_caches = 3
[root@localhost ~]
# cat /proc/sys/vm/drop_caches
3
[root@localhost ~]
#
|
永久生效
1
2
3
4
5
6
|
[root@localhost ~]
# cp /etc/sysctl.conf{,.bak}
[root@localhost ~]
# vim /etc/sysctl.conf
#vm.drop_caches=1
#vm.drop_caches=2
vm.drop_caches=3
[root@localhost ~]
# sysctl -p
|
sysctl命令用于运行时配置内核参数,这些参数位于/proc/sys目录下。sysctl配置与显示在/proc/sys目录中的内核参数.可以用sysctl来设置或重新设置联网功能,如IP转发、IP碎片去除以及源路由检查等。用户只需要编辑/etc/sysctl.conf文件,即可手工或自动执行由sysctl控制的功能。
-w 临时改变某个指定参数的值,如
sysctl -w net.ipv4.ip_forward=1
-a 显示所有的系统参数
-p 从指定的文件加载系统参数,如不指定即从/etc/sysctl.conf中加载
另外,可以使用sync命令来清理文件系统缓存,还会清理僵尸(zombie)对象和它们占用的内存
1
|
[root@localhost ~]
# sync
|
sync命令用于强制被改变的内容立刻写入磁盘,更新超块信息。
在Linux/Unix系统中,在文件或数据处理过程中一般先放到内存缓冲区中,等到适当的时候再写入磁盘,以提高系统的运行效率。sync命令则可用来强制将内存缓冲区中的数据立即写入磁盘中。用户通常不需执行sync命令,系统会自动执行update或bdflush操作,将缓冲区的数据写 入磁盘。只有在update或bdflush无法执行或用户需要非正常关机时,才需手动执行sync命令。
如果在执行这些操作时正在写数据,那么实际上在数据到达磁盘之前就将它从文件缓存中清除掉了,这可能会造成很数据的丢失。
在linux中/proc/sys/vm/vfs_cache_pressure这个文件会告诉内核,当清理inoe/dentry缓存时应该用什么样的优先级。
1
2
3
|
[root@localhost ~]
# cat /proc/sys/vm/vfs_cache_pressure
100
[root@localhost ~]
#
|
这个是默认值,内核会尝试重新声明dentries和inodes,并采用一种相对于页面缓存和交换缓存比较”合理”的比例。
减少vfs_cache_pressure的值,会导致内核倾向于保留dentry和inode缓存。
增加vfs_cache_pressure的值,(即超过100时),则会导致内核倾向于重新声明dentries和inodes
小于100的值不会导致缓存的大量减少,超过100的值则会告诉内核你希望以高优先级来清理缓存。
其实无论vfs_cache_pressure的值采用什么值,内核清理缓存的速度都是比较低的。如果将此值设置为10000,系统将会将缓存减少到一个合理的水平。
swap分区添加
一、使用分区的方式
1.直接安装系统的时候在文件系统类型里选择swap添加分区
2.如果安装系统时候忘记添加swap分区,通过如下步骤添加:
这里直接把上次创建的/dev/sdb1修改为swap分区
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
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
[root@justin ~]
# fdisk /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): p
Disk
/dev/sdb
: 8589 MB, 8589934592 bytes
255 heads, 63 sectors
/track
, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical
/physical
): 512 bytes / 512 bytes
I
/O
size (minimum
/optimal
): 512 bytes / 512 bytes
Disk identifier: 0x9adeb999
Device Boot Start End Blocks Id System
/dev/sdb1
1 393 3156741 83 Linux
/dev/sdb4
394 1044 5229157+ 5 Extended
/dev/sdb5
394 786 3156741 83 Linux
/dev/sdb6
787 1044 2072353+ 83 Linux
Command (m
for
help): t ;修改文件系统类型
Partition number (1-6): 1 ;指sdb1分区
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): w
The partition table has been altered!
Calling ioctl() to re-
read
partition table.
WARNING: Re-reading the partition table failed with error 16: 设备或资源忙. ;因为之前挂载了,最好修改钱卸载掉
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.
[root@justin ~]
# fdisk -l /dev/sdb
Disk
/dev/sdb
: 8589 MB, 8589934592 bytes
255 heads, 63 sectors
/track
, 1044 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical
/physical
): 512 bytes / 512 bytes
I
/O
size (minimum
/optimal
): 512 bytes / 512 bytes
Disk identifier: 0x9adeb999
Device Boot Start End Blocks Id System
/dev/sdb1
1 393 3156741 82 Linux swap / Solaris
/dev/sdb4
394 1044 5229157+ 5 Extended
/dev/sdb5
394 786 3156741 83 Linux
/dev/sdb6
787 1044 2072353+ 83 Linux
[root@justin ~]
# free
total used
free
shared buffers cached
Mem: 1030796 113716 917080 0 17400 58992
-/+ buffers
/cache
: 37324 993472
Swap: 2097144 0 2097144
[root@justin ~]
# mkswap /dev/sdb1
/dev/sdb1
: 设备或资源忙
[root@justin ~]
# umount /dev/sdb1
[root@justin ~]
# mkswap /dev/sdb1 ;格式化为swap分区
Setting up swapspace version 1, size = 3156736 KiB
no label, UUID=b02fa6eb-b2ff-445b-a22a-9789263c729b
[root@justin ~]
# swapon /dev/sdb1 ;激活swap分区
[root@justin ~]
# free
total used
free
shared buffers cached
Mem: 1030796 115984 914812 0 17412 59012
-/+ buffers
/cache
: 39560 991236
Swap: 5253876 0 5253876
[root@justin ~]
# swapon -s ;显示swap分区列表
Filename Type Size Used Priority
/dev/sda3
partition 2097144 0 -1
/dev/sdb1
partition 3156732 0 -2
[root@justin ~]
# vim /etc/fstab
/dev/sdb1
/mnt/sdb1
swap defaults 0 0
[root@justin ~]
# swapon -a ;加载swap分区
[root@justin ~]
# swapoff /dev/sdb1 ;卸载swap分区
[root@justin ~]
# free
total used
free
shared buffers cached
Mem: 1030796 116416 914380 0 17276 61604
-/+ buffers
/cache
: 37536 993260
Swap: 2097144 0 2097144
[root@justin ~]
# swapon /dev/sdb1
[root@justin ~]
# free
total used
free
shared buffers cached
Mem: 1030796 118296 912500 0 17280 61616
-/+ buffers
/cache
: 39400 991396
Swap: 5253876 0 5253876
[root@justin ~]
#
|
至此swap分区创建完成
二、使用文件的方式:
文件写入swap的时候分区会比文件快,所以最好还是使用分区的方式,以下创建一个200M的swap:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
[root@justin ~]
# grep SwapTotal /proc/meminfo
SwapTotal: 5253876 kB
[root@justin ~]
# dd if=/dev/zero of=/home/swapfile bs=100M count=2
记录了2+0 的读入
记录了2+0 的写出
209715200字节(210 MB)已复制,2.19593 秒,95.5 MB/秒
[root@justin ~]
# mkswap /home/swapfile
mkswap:
/home/swapfile
: warning: don't erase bootbits sectors
on whole disk. Use -f to force.
Setting up swapspace version 1, size = 204796 KiB
no label, UUID=b977d4b9-acfb-4feb-8fb6-22b2ea132a42
[root@justin ~]
# swapon /home/swapfile
[root@justin ~]
# vim /etc/fstab
/home/swapfile
swap swap defaults 0 0
[root@justin ~]
# swapon -a
[root@justin ~]
# grep SwapTotal /proc/meminfo
SwapTotal: 5458668 kB
[root@justin ~]
#
|
至此swap分区创建完成
swap清理
1
|
[root@localhost nagios]
# swapoff -a && swapon -a
|
注意:这样清理有个前提条件,空闲的内存必须比已经使用的swap空间大
扩展:
dd功能是把指定的输入文件拷贝到指定的输出文件中,并且在拷贝过程中可以进行格式转换,
1
|
[root@justin ~]
# dd if=/dev/zero of=/home/swapfile bs=100M count=2
|
if=/dev/zero if的意思是i代表input 就是输入的意思f=file代表文件 ,if=/dev/zero 说明使用/dev/zero 这个文件作为输入,
of=/home/swapfile of代表output file ,就是输出文件,就是我们生成的那个文件的文件名,我们这里名字叫做swapfile,
ibs=1bytes 一次读入1个字节(即一个块大小为 1个字节)。
obs=1bytes 一次写入1 个字节(即一个块大小为1个字节)。
bs=1bytes 同时设置读写块的大小为 1bytes ,可代替 ibs 和 obs ,如果bs=1k指定数字的地方乘以以下列相应的数字。即bs=1*1024bytes,bs=2b=2*512=2024bytes
b=512, c=1, k=1024, w=2, xm=number m,
1 byte(字节) = 8 bits (位)
1KiB= 1,024 bytes
1MiB= 1,048,576 bytes
1GiB= 1,073,741,824 bytes
1TiB= 1,099,511,627,776 bytes
cbs=1bytes 一次转换 1个字节,即转换缓冲区大小。
skip=1blocks 从输入文件if 后面的部分开头跳过1个块后再开始复制。
1
|
#dd if=abc.gz of=abc.gz.bak2 bs=1k skip=10000 count=70000
|
表示跳过abc.tz前10000K的输入开始复制
seek=1blocks 从输出文件of 后面的部分开头跳过1个块后再开始复制。(通常只有当输出文件是磁盘或磁带时才有效)。
count代表使用几个块,bs乘以count大小为该文件的总大小,
/dev/null,外号叫"黑洞",它等价于一个只写文件,所有写入它的内容都会永远丢失.,而尝试从它那儿读取内容则什么也读不到。如果不想让消息以标准输出显示或写入文件,那么可以将消息重定向到它。
/dev/zero主要的用处是用来创建一个指定长度用于初始化的空文件,就像临时交换文件。
使用dd命令来测试硬盘的写入速度
1
2
3
|
[root@justin ~]
# dd if=/dev/zero of=/tmp/1Gbytes bs=4k count=256000 oflag=dsync
[root@justin ~]
# dd if=/dev/zero of=/tmp/1Gbytes bs=4k count=256000 conv=fdatasync
|
两个都是往硬盘中写入1 Gbytes的数据,只是第一个的速度慢的要命。使用dsync,dd会从/dev/zero中,每次读取4Kbytes数据,然后直接写入到硬盘当中,重复此步骤,直到共读取并且写入了1 Gbytes的数据。使用fdatasync,dd会从/dev/zero中一次性读取1 Gbytes的数据,写入到磁盘的缓存中,然后再从磁盘缓存中读取,一次性写入到硬盘当中。