0. 背景
inux用户安装Linux操作系统时遇到的一个常见的难以决定的问题就是如何正确地评估各分区大小,以分配合适的硬盘空间。普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某个文件时,这个文件因为受上层文件系统的限制,也不能跨越多个分区来存放,所以也不能同时放到别的磁盘上。而遇到出现某个分区空间耗尽时,解决的方法通常是使用符号链接,或者使用调整分区大小的工具,但这只是暂时解决办法,没有从根本上解决问题。随着Linux的逻辑卷管理功能的出现,这些问题都迎刃而解,用户在无需停机的情况下可以方便地调整各个分区大小。
1. 硬盘类型 /dev/sda VS /dev/hda
/dev/sda
/dev/sda1
/dev/sda2
/dev/sda3
而又的安装时硬盘驱动设备名为
/dev/hda
/dev/hda1
Q:sda和hda有什么区别那?
A: HDA是使用了ide接口的硬盘的名称.SDA是sata接口的硬盘的名称.在最新的2.6.19内核里,所有的硬盘都叫SDA了.
硬盘接口分为:
- ide (integrated drive electronics) 把盘体和控制器集成在一起
- sata (serial ATA(advanced technology attachment))
- scsi (small computer system interface)
- 光纤通道 fibre channel
其中hda、hdb分别代表第一个IDE、第二个IDE。假如你电脑上插有2个IDE硬盘,就会出现hda、hdb吗?不一定,因为貌似IDE硬盘默认有两个部分,Master和Slave,即主分区和扩展分区,而且a、b是根据IDE接口插槽顺序来分的。这样的话,第一IDE插槽主分区为hda,扩展分区为hdb,第二IDE插槽主分区为hdc,扩展分区为hdd。
但是SATA硬盘好像没有扩展分区,而且Linux识别SATA等类型装置的顺序不是按插槽顺序来的,是按照设备被侦测到的顺序来定的,比如SATA的第1、5插槽分别插有硬盘,电脑上还插有一个USB,那么启动Linux的时候,先后侦测到SATA的第1、5插槽的硬盘和USB设备,那么分配的名称就分别是sda,sdb,sdc。
但貌似,Ubuntu自8.04起,所有硬盘都编号为“sdx”,即不管IDE还是SATA,一律认作SCIS硬盘。
2. 分区 (Partition)
计算机中存放信息的主要的存储设备就是硬盘,但是硬盘不能直接使用,必须对硬盘进行分割,分割成的一块一块的硬盘区域就是磁盘分区。在传统的磁盘管理中,将一个硬盘分为两大类分区:主分区和扩展分区。主分区是能够安装操作系统,能够进行计算机启动的分区,这样的分区可以直接格式化,然后安装系统,直接存放文件。
在一个MBR分区表类型的硬盘中最多只能存在4个主分区。如果一个硬盘上需要超过4个以上的磁盘分块的话,那么就需要使用扩展分区了。如果使用扩展分区,那么一个物理硬盘上最多只能3个主分区和1个扩展分区。扩展分区不能直接使用,它必须经过第二次分割成为一个一个的逻辑分区,然后才可以使用。一个扩展分区中的逻辑分区可以任意多个。
磁盘分区后,必须经过格式化才能够正式使用,格式化后常见的磁盘格式有:FAT(FAT16)、FAT32、NTFS、ext2、ext3等。
那么sda1、sda2又分别代表什么呢?代表分区(Partition),比如
- P1:/dev/hda1
- P2:/dev/hda2
- L1:/dev/hda5
- L2:/dev/hda6
- L3:/dev/hda7
- L4:/dev/hda8
- L5:/dev/hda9
为什么没有hda3、4呢?因为P1~4保存给了Primary和Extended分区。一个硬盘的结构如下:
MBR|主分区1|主分区2|主分区3|主分区4(扩展分区)|, 其中扩展分区可以分为: |逻辑分区1|逻辑分区2|……|逻辑分区n|
所以说上面的P1、2指明系统有两个主分区,L1~5代表有5个逻辑分区。主分区(包括扩展分区)的总个数不能超过四个;也不能把扩展分区包围在主分区之间。
参考: http://blog.csdn.net/zollty/article/details/7001950
fdisk 命令
root@dev:/home/s1# fdisk -l
Disk /dev/sda: 250.1 GB, 250059350016 bytes //这个硬盘有250.1 GB的容量
255 heads, 63 sectors/track, 30401 cylinders, total 488397168 sectors //255个磁头;63个扇区每磁道,30401个磁柱
Units = sectors of 1 * 512 = 512 bytes //每个 cylinder(磁柱)的容量是512字节
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000d7bf1
存储容量=磁道(柱面)数×磁头数×每道扇区数×每扇区字节数 = 30401 * 255 * 63 * 512 = 25396387380 bytes
Device Boot Start End Blocks Id System //Start (开始)/End (结束):表示的一个分区从X sector开始/结束
/dev/sda1 * 2048 484298751 242148352 83 Linux //引导(Boot):表示引导分区,在上面的例子中 hda1 是引导分区
/dev/sda2 484300798 488396799 2048001 5 Extended //Blocks:表示的意思的确是容量的意思,其单位是K
/dev/sda3 484298752 484300797 1023 83 Linux
/dev/sda5 484300800 488396799 2048000 82 Linux swap / Solaris //大小,2048000/1024=2G
?
这里有一个主分区sda1,一个扩展分区sda2,sda2包括两个逻辑分区sda3和sda4.
硬盘总容量=主分区(包括扩展分区)总容量
- 主分区大小为 242148352 /1024 = 236473 M = 236 G
- 扩展分区大小为:2014001 / 1024 = 2000M = 2G
- 磁盘总容量大小为:236 + 2 = 238G
扩展分区容量=逻辑分区总容量
我们估算一个硬盘是否完全被划分,我们只要看 fdisk -l 输出的内容中的 cylinders(柱体) 上一个分区的End 和 下一个分区的Start是不是一个连续的数字,另外要看一下每个硬盘设备的fdisk -l 的开头部份,看一下他的 cylinders(柱体)的值。可见上图中,扩展分区都分完了。
df -h 命令:
注: df 下没有显示swap分区
改变Linux分区大小
1. 建议在安装Ubuntu的过程中,选择手动方法进行磁盘分区。可参考 http://blog.sina.com.cn/s/blog_56a70c0401018dki.html 中的具体步骤。
2. linux安装好以后,根分区容量一般是不允许改变的。
LVM can be set up after the system is installed. But putting the root partition on the LVM after the fact is quite difficult and probably would be better done with a reinstallation. Furthermore, it is not possible to just create a LVM on a already mounted partition.
LVM可以在系统装好后安装。但是将根分区放进LVM是非常困难的,因此建议重装系统的时候再设置。而且,在已经挂载的分区上创建LVM是不行的。
3.实在要改变,推荐用gparted-LiveCD进行调整
(1)、准备
1、下载最新版本的gparted ISO 镜像文件:http://gparted.sourceforge.net/
2、将gparted镜像文件刻录成光盘或压制在U盘上制成LiveUSB
3、建议备份重要数据到移动硬盘上
4、在BIOS中,将启动顺序设置为首先光驱启动(如果是用LiveUSB,应设为USB-HDD)
(2)、调整分区
1、将光盘放入光驱(如果是用LiveUSB,插上U盘),重启电脑. 这时候我遇到一个错误:vesamenu.c32 not a com32r image。 解决办法是到Ubuntu系统中找到这个文件,替换掉USB上的这个文件,它存在于两个文件夹中。
2、进入gparted启动界面,直接选Defalt settings
3、第二个界面继续按回车7 y: O. l3 A" E/ P N0 L: j
4、接下来选语言,输入“26”回车(就是简体中文,尽管汉化不全)
5、接着提示将要进入X-Windows界面,回车
6、进入gparted,就会发现和瘟到死的PQ相似的界面,实际操作也是一样的,而且也支持瘟到死分区的调整
7、点击你要腾出空间的分区,弹出右键菜单选择“Resize/Move”& Z)
8、用鼠标托动或数字精确调整要释放的空间大小,若要释放在分区头部拉左侧的控制条(输入第一行数值),若要释放在分区尾部拉右侧的控制条(输入第三行数值),调整好之后点“更改大小/移动”按钮。
9、点击欲扩大容量的分区,弹出右键菜单选择“Resize/Move”
10、按照第8步的方法操作,只是现在变成扩大分区容量而已
11、点击“Edit”菜单,选择“Apply All Operations”3
12、再次确认要调整分区容量后,gparted开始调整分区,完成后点“Close”按钮
13、点“gparted”菜单,选“Quit”关闭gparted窗口,再双击左上角的“Exit”按钮退出gparted系统
14、在弹出的窗口中选“Reboot”重启电脑,退出时系统会提示你取出光盘
(3)、可能遇到的问题
可能会发生swap分区丢失的情况,可在终端中用“free -m”命令查看swap分区是否激活(是否显示容量),如果未激活,可用“sudo mkswap /dev/sdaX”命令(X为swap分区的编号)进行激活,并将激活所得的UUID码替换掉“/etc/fstab”文件(需要管理员权限)中原来 swap分区的UUID编码,重启后即可自动激活挂载
具体操作方法,请进Ubuntu官方论坛中查找,有教程帖8 z. \0 s8 }- M& c
警告:对swap分区的激活操作及对fstab文件的修改应谨慎,必需仔细核对修改的值
在界面上缩小sda1的大小,并创建新的分区,重启电脑后终于看到一个新的分区了,还有一些未分配空间。接下来就可以用下面的LVM方法来创建LVM啦。。
3. 挂载和挂载点
一个挂载点就是一个文件夹,将分区挂载到一个挂载点,挂载点就成了分区的入口。没有挂载分区的挂载点将使用根目录的空间,没有挂载到挂载点的分区是无法访问的,如上边第四个逻辑分区。
例如,如果分区 /dev/hda5 被 挂载在 /usr 上,这意味着所有在 /usr 之下的文件和目录在物理意义上位于 /dev/hda5 上。因此文件 /usr/share/doc/FAQ/txt/Linux-FAQ 被储存在 /dev/hda5上,而文件 /etc/X11/gdm/Sessions/Gnome 却不是。
继续以上的例子,/usr 之下的一个或多个目录还有可能是其它分区的挂载点。例如,某个分区(假设为,/dev/hda7)可以被挂载到 /usr/local 下,这意味着 /usr/local/man/whatis 将位于 /dev/hda7 上而不是 /dev/hda5 上。
linux系统中每个分区都是一个文件系统,都有自己的目录层次结构。linux会将这些分属不同分区的、单独的文件系统按一定的方式形成一个系统的总的目录层次结构。将一个文件系统的顶层目录挂到另一个文件系统的子目录上,使它们成为一个整体,称为挂载。把该子目录称为挂载点。
注意:1、挂载点必须是一个目录。
2、一个分区挂载在一个已存在的目录上,这个目录可以不为空,但挂载后这个目录下以前的内容将不可用。对于其他操作系统建立的文件系统的挂载也是这样。但是需要理解的是:光盘、软盘、其他操作系统使用的文件系统的格式与linux使用的文件系统格式是不一样的。光盘是ISO9660;软盘是fat16或ext2;windows NT是fat16、NTFS;windows98是fat16、fat32;windows2000和windowsXP是fat16、fat32、NTFS。
挂载前要了解linux是否支持所要挂载的文件系统格式。
挂载时使用mount命令:
格式:mount [-参数] [设备名称] [挂载点]
其中常用的参数有
-t<文件系统类型> 指定设备的文件系统类型,常见的有:
minix linux最早使用的文件系统
ext2 linux目前常用的文件系统
msdos MS-DOS的fat,就是fat16
vfat windows98常用的fat32
nfs 网络文件系统
iso9660 CD-ROM光盘标准文件系统
ntfs windows NT 2000的文件系统
hpfs OS/2文件系统
auto 自动检测文件系统
-o<选项> 指定挂载文件系统时的选项。有些也可用在/etc/fstab中。常用的有
codepage=XXX 代码页
iocharset=XXX 字符集
ro 以只读方式挂载
rw 以读写方式挂载
nouser 使一般用户无法挂载
user 可以让一般用户挂载设备
提醒一下,mount命令没有建立挂载点的功能,因此你应该确保执行mount命令时,挂载点已经存在。(不懂?说白了点就是你要把文件系统挂载到哪,首先要先建上个目录。这样OK?)
例子:windows98装在hda1分区,同时计算机上还有软盘和光盘需要挂载。
# mk /mnt/winc
# mk /mnt/floppy
# mk /mnt/cdrom
# mount -t vfat /dev/hda1 /mnt/winc
# mount -t msdos /dev/fd0 /mnt/floppy
# mount -t iso9660 /dev/cdrom /mnt/cdrom
现在就可以进入/mnt/winc等目录读写这些文件系统了。
自动挂载:
在/etc/fstab文件里,第一列是挂载的文件系统的设备名,第二列是挂载点,第三列是挂载的文件系统类型,第四列是挂载的选项。添加新行实现自动挂载:
/dev/hdb1 /mnt/winc vfat defaults,codepage=936,iocharset=cp936 0 0
/dev/hda5 /mnt/wind vfat defaults,codepage=936,iocharset=cp936 0 0
4. LVM几个基本概念
*物理存储介质(PhysicalStorageMedia):指系统的物理存储设备:磁盘,如:/dev/hda、/dev/sda等,是存储系统最底层的存储单元。
*物理卷(Physical Volume,PV):可以在上面建立卷组的媒介,可以是硬盘分区,也可以是硬盘本身或者回环文件(loopback file),它是LVM的基本存储逻辑块。物理卷包括一个特殊的header,其余部分被切割为一块块物理区域(physical extents)。
*物理块(Physical Extent,PE):每一个物理卷PV被划分为称为PE(Physical Extents)的基本单元,具有唯一编号的PE是可以被LVM寻址的最小单元。PE的大小是可配置的,默认为4MB。所以物理卷(PV)由大小等同的基本单元PE组成。
*卷组(Volume Group,VG):将一组物理卷收集为一个管理单元,类似于非LVM系统中的物理磁盘,其由一个或多个物理卷PV组成。可以在卷组上创建一个或多个LV(逻辑卷)。
*逻辑卷(Logical Volume,LV):虚拟分区,由物理区域(physical extents)组成,逻辑卷建立在卷组VG之上。在逻辑卷LV之上可以建立文件系统(比如/home或者/usr等)。
*逻辑块(Logical Extent,LE):逻辑卷LV也被划分为可被寻址的基本单位,称为LE。在同一个卷组中,LE的大小和PE是相同的,并且一一对应。
LVM抽象模型
优点
比起正常的硬盘分区管理,LVM更富于弹性:
- 使用卷组(VG),使众多硬盘空间看起来像一个大硬盘。
- 使用逻辑卷(LV),可以创建跨越众多硬盘空间的分区。
- 可以创建小的逻辑卷(LV),在空间不足时再动态调整它的大小。
- 在调整逻辑卷(LV)大小时可以不用考虑逻辑卷在硬盘上的位置,不用担心没有可用的连续空间。It does not depend on the position of the LV within VG, there is no need to ensure surrounding available space.
- 可以在线(online)对逻辑卷(LV)和卷组(VG)进行创建、删除、调整大小等操作。LVM上的文件系统也需要重新调整大小,某些文件系统也支持这样的在线操作。
- 无需重新启动服务,就可以将服务中用到的逻辑卷(LV)在线(online)/动态(live)迁移至别的硬盘上。
- 允许创建快照,可以保存文件系统的备份,同时使服务的下线时间(downtime)降低到最小。
这些优点使得LVM对服务器的管理非常有用,对于桌面系统管理的帮助则没有那么显著,你需要根据实际情况进行取舍。
缺点:
- 只能在Linux上使用。对于其他操作系统(如FreeBSD, Windows等),尚未有官方支持。
- 在系统设置时需要更复杂的额外步骤。
- 假如你使用的是btrfs文件系统,那么它所提供的子卷(subvolume)实际上已经时一层可动态调整的存储层,此时再用LVM就显得多余了。
操作:
要创建一个LVM系统,一般需要经过以下步骤:
1、创建分区: 使用分区工具(如:fdisk等)创建LVM分区,方法和创建其他一般分区的方式是一样的,区别仅仅是LVM的分区类型为8e。
2、创建物理卷:创建物理卷的命令为pvcreate,利用该命令将希望添加到卷组的所有分区或者磁盘创建为物理卷。
将整个磁盘创建为物理卷的命令为:#pvcreate /dev/hdb
将单个分区创建为物理卷的命令为:#pvcreate /dev/hda5
3、创建卷组:创建卷组的命令为vgcreate,将使用pvcreate建立的物理卷创建为一个完整的卷组:
#vgcreate web_document /dev/hda5 /dev/hdb
vgcreate命令第一个参数是指定该卷组的逻辑名:web_document。后面参数是指定希望添加到该卷组的所有分区和磁盘。vgcreate 在创建卷组web_document以外,还设置使用大小为4MB的PE(默认为4MB),这表示卷组上创建的所有逻辑卷都以4MB为增量单位来进行扩充 或缩减。由于内核原因,PE大小决定了逻辑卷的最大大小,4MB的PE决定了单个逻辑卷最大容量为256GB,若希望使用大于256G的逻辑卷则创建卷组 时指定更大的PE。PE大小范围为8KB到512MB,并且必须总是2的倍数(使用-s指定,具体请参考manvgcreate)。(centos 6.2系统已发现没有这种限制)
4、激活卷组
为了立即使用卷组而不是重新启动系统,可以使用vgchange来激活卷组:
#vgchange -ay web_document
5、添加新的物理卷到卷组中
当系统安装了新的磁盘并创建了新的物理卷,而要将其添加到已有卷组时,就需要使用vgextend命令:
#vgextend web_document /dev/hdc1
这里/dev/hdc1是新的物理卷。
6、从卷组中删除一个物理卷
要从一个卷组中删除一个物理卷,首先要确认要删除的物理卷没有被任何逻辑卷正在使用,就要使用pvdisplay命令察看一个该物理卷信息:
如果某个物理卷正在被逻辑卷所使用,就需要将该物理卷的数据备份到其他地方,然后再删除。删除物理卷的命令为vgreduce:
#vgreduce web_document /dev/hda1
7、创建逻辑卷
创建逻辑卷的命令为lvcreate:
#lvcreate -L1500 -n www1 web_document
该命令就在卷组web_document上创建名字为www1,大小为1500M的逻辑卷,并且设备入口为 /dev/web_document/www1(web_document为卷组名,www1为逻辑卷名)。如果希望创建一个使用全部卷组的逻辑卷,则需 要首先察看该卷组的PE数,然后在创建逻辑卷时指定:
#vgdisplay web_document | grep"TotalPE"
TotalPE45230
#lvcreate -l45230 web_document -n www1
8、创建文件系统
笔者推荐使用reiserfs文件系统,来替代ext2和ext3:
创建了文件系统以后,就可以加载并使用它:
#mkdir/data/wwwroot
#mount /dev/web_document/www1/data/wwwroot
如果希望系统启动时自动加载文件系统,则还需要在/etc/fstab中添加内容:
/dev/web_document/www1/data/wwwrootreiserfsdefaults12
9、删除一个逻辑卷
删除逻辑卷以前首先需要将其卸载,然后删除:
#umount /dev/web_document/www1 #lvremove /dev/web_document/www1
10、扩展逻辑卷大小
LVM提供了方便调整逻辑卷大小的能力,扩展逻辑卷大小的命令是lvextend:
lvextend -L12G /dev/web_document/www1
上面的命令就实现将逻辑卷www1的大小扩招为12G。
lvextend -L +1G /dev/web_document/www1
上面的命令就实现将逻辑卷www1的大小增加1G。
增加了逻辑卷的容量以后,就需要修改文件系统大小以实现利用扩充的空间。笔者推荐使用reiserfs文件系统来替代ext2或者ext3。因此这里仅 仅讨论reiserfs的情况。Reiserfs文件工具提供了文件系统大小调整工具:resize_reiserfs。对于希望调整被加载的文件系统大 小:
#resize_reiserfs -f /dev/web_document/www1
一般建议最好将文件系统卸载,调整大小,然后再加载:
#umount /dev/web_document/www1 #resize_reiserfs /dev/web_document/www1 #mount-treiserfs /dev/web_document/www1/data/wwwroot
对于使用ext2或ext3文件系统的用户可以考虑使用工具 resize2fs 。
11、减少逻辑卷大小
使用 lvreduce 即可实现对逻辑卷的容量,同样需要首先将文件系统卸载:
#umount /data/wwwroot #resize_reiserfs -s -2G /dev/web_document/www1 #lvreduce -L -2G /dev/web_document/www1 #mount-treiserfs /dev/web_document/www1/data/wwwroot
lvreduce 可以使用两种类型的size:
(1)指定减少的size
lvreduce --size -40G /dev/vg0/foo
(2)指定减少到的size
lvreduce --size 80G /dev/vg0/foo
实际测试(RedHat 6.5 环境,ext3 文件系统):
1. 缩小 lv 的容量
缩小 lv 容量之前,一定要先 umount,然后使用 resize2fs 命令将ext2/ext3文件系统的空间先缩小(不同的文件系统使用不同的命令),然后再使用 lvreduce 命令缩小 lv,然后再 mount。不是这个过程的话,文件系统非常有可能崩溃。
[root@rh65 ~]# umount /home [root@rh65 ~]# e2fsck -f /dev/mapper/vg_rh65-lv_home e2fsck 1.41.12 (17-May-2010) Pass 1: Checking inodes, blocks, and sizes Pass 2: Checking directory structure Pass 3: Checking directory connectivity Pass 4: Checking reference counts Pass 5: Checking group summary information /dev/mapper/vg_rh65-lv_home: 38/80543744 files (10.5% non-contiguous), 23715920/322174976 blocks [root@rh65 ~]# resize2fs /dev/mapper/vg_rh65-lv_home 800G resize2fs 1.41.12 (17-May-2010) Resizing the filesystem on /dev/mapper/vg_rh65-lv_home to 209715200 (4k) blocks. The filesystem on /dev/mapper/vg_rh65-lv_home is now 209715200 blocks long. [root@rh65 ~]# lvreduce --size 800G /dev/mapper/vg_rh65-lv_home WARNING: Reducing active logical volume to 800.00 GiB THIS MAY DESTROY YOUR DATA (filesystem etc.) Do you really want to reduce lv_home? [y/n]: y Reducing logical volume lv_home to 800.00 GiB Logical volume lv_home successfully resized [root@rh65 ~]# fsck /dev/mapper/vg_rh65-lv_home fsck from util-linux-ng 2.17.2 e2fsck 1.41.12 (17-May-2010) /dev/mapper/vg_rh65-lv_home: clean, 38/52428800 files, 21950847/209715200 blocks [root@rh65 ~]# mount /dev/mapper/vg_rh65-lv_home /home
2. 增加 lv 容量
先使用 lvextend 增加 lv 容量,在使用 resize2fs 增加文件系统的容量,使得两者的size一直,否则重启后会出现 fsck 错误。
[root@rh65 ~]# lvextend -L +500G /dev/mapper/vg_rh65-lv_root Extending logical volume lv_root to 1.07 TiB Logical volume lv_root successfully resized [root@rh65 ~]# resize2fs /dev/mapper/vg_rh65-lv_root resize2fs 1.41.12 (17-May-2010) Filesystem at /dev/mapper/vg_rh65-lv_root is mounted on /; on-line resizing required old desc_blocks = 19, new_desc_blocks = 69 Performing an on-line resize of /dev/mapper/vg_rh65-lv_root to 288358400 (4k) blocks. The filesystem on /dev/mapper/vg_rh65-lv_root is now 288358400 blocks long.
命令列表:
vgs,pvs,lvs
e2fsadm(8), lvchange(8), lvcreate(8), lvdisplay(8),
lvextend(8), lvmchange(8), lvmdiskscan(8),
lvmcreate_initrd(8), lvmsadc(8), lvmsar(8),
lvreduce(8), lvremove(8), lvrename(8),
lvscan(8), pvchange(8), pvcreate(8), pvdata(8),
pvdisplay(8), pvmove(8), pvscan(8), vgcfgbackup(8),
vgcfgrestore(8), vgchange(8), vgck(8), vgcreate(8),
vgdisplay(8), vgexport(8), vgextend(8), vgimport(8),
vgmerge(8), vgmknodes(8), vgreduce(8), vgremove(8),
vgrename(8), vgscan(8), vgsplit(8)
以上文字由网络上搜到的文字加工而成。主要参考材料包括:
https://wiki.archlinux.org/index.php/LVM_ (%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)
http://blog.csdn.net/zollty/article/details/7001950
(文/SammyLiu)
本文来源:http://www.cnblogs.com/sammyliu/p/4157491.html
如果给你带来帮助,欢迎微信或支付宝扫一扫,赞一下。