分类: LINUX
2015-05-19 11:20:55
原文地址:unionfs(联合文件系统)笔记 作者:cywcdwxjf
很早就想把这个文件系统的文档读一读,一直没有静下心来。今天看到fans上有人翻译了slax上的一篇文章,所以借别人的劳动成功来偷点懒。做了小小的修改并加了一点个人的理解。
原文地址:
翻译地址:
已有的中文文章:
一个联合文件系统(Unionfs)的例子
这个材料给出了一个使用联合文件系统(unionfs)的例子,即在slax linux livecd实现。Unionfs
是2004年在stony
brook大学开始的,它是一个可叠放的联合文件系统,它能够联合多个目录(因此可称为分支)同时独立地保持它们的物理内容。它允许任何ro和rw分支的
结合,同时允许在分支中修改和删除不使用的分支。Unionfs可以使用在几个方面,例如联合在不同磁盘上的不同的文件系统到一个home目录,或者把几
张cd合并成一个统一的归档镜像。所以,具有复制可写功能的unionfs可以用来把ro和rw的文件系统合并起来,并且实现了允许修改只读文件系统并把
这些修改保存在可写文件系统。
Slax是一个192兆大的linux-live发行版,目的是将linux操作系统的全部特征压制到一个便携式的媒介(U盘或者mini-CD)中,并
且允许在任何电脑上不需要安装而启动linux。它甚至可以在没有硬盘的电脑上运行。Unionfs是slax系统中最重要的部分,它使slax具有完全
可写的根目录结构,从而无论是表面上还是运行方式上slax等同于一个真实的linux操作系统。所以首先让我们谈一下unionfs。
启动时加载unionfs
要使unionfs运行,你需要通过编译源代码建立一个linux内核模块。Unionfs可以作为扩充模块用于版本在2.4.20或2.6.9和更新的linux内核。从ftp下载最新的版本并且解开压缩包。
$tar -xzf unionfs-x-y-z.tar.gz
然后进入解压出来的文件夹,仔细阅读文件夹中的README和INSTALL两个文件。其中有很多关于如何避免问题的说明。之前如果你知道加模块可能会使编译调试不成功会对整个编译过程很有用。调试信息对报告错误很有用,但是值得注意的是内核模块大小的增加。两个参数必须设定使调试完全不起作用(即调试信息不写入模块中)。
在包含源码的目录下建立一个fistdev.mv文件,写入下面代码:
EXTRACFLAGS=-DUNIONFS_NDEBUG
UNIONFS_DEBUG_CFLAG=
编译出来的内核模块没有调试信息大约90KB,而有调试信息的是5MB(你可以下载fistdev.mv来为slax编译unionfs)。
另一件重要的使编译工作顺利的事是下载和解压你正使用的内核源码包,并且修改unionfs中Makefile中的LINUXSRC变量,添加你刚才解压的目录路径(某些时候可以自动检测到)。
接下来,使用下面的命令可以将unionfs模块建立并安装在/lib/modules$(KernelVersion)/kernel/fs/unionfs下:
$make
$make install
$depmod -a
使用unionfs
在接下面的例子中我们把两个文件夹的内容合并到仅仅一个文件夹/mnt/union中。假定所有的文件夹都已经存在。
$modprobe unionfs
$mount –t unionfs –o dirs=/mnt/cdrom1=ro:/mnt/cdrom2=ro unionfs /mnt/union
现在,文件夹/mnt/union包含所有/mnt/cdrom1和/mnt/cdrom2中的文件,它们被合并在一起并且都是只读的。如果两个目录中有相同文件名的文件,那么cdrom1中的文件具有优先权(因为cdrom1在命令中列在左边)。
使用unionctl
Unionctl(同时还有uniondbg)是一个编译unionfs时建立并安装在/usr/local/sbin中的工具。Unionctl被用来
处理存在的union(如上面的/mnt/union),列出、增加、修改或者删除存在的分支。下面是一些使用unionctl命令准确列出所有信息的简
单例子。
$unionctl /mnt/union --list
将会显示下面的信息:
/mnt/cdrom1 (r-)
/mnt/cdrom2 (r-)
增加另一个目录(/mnt/cdrom3)到union中使用
$unionctl /mnt/union --add --after /mnt/cdrom2 --mode ro /mnt/cdrom3
再用unionctl –list将会显示
/mnt/cdrom1 (r-)
/mnt/cdrom2 (r-)
/mnt/cdrom3 (r-)
当你改变分支本身内容时,执行下面的命令强制更新union目录。
$uniondbg -g /mnt/union
写入union目录
合并只读文件夹在很多情况下是很有用的,但是在加入一个读写分支之前,union目录本身仍然是只读的。这种情况下,所有的改变都储存在最左边的分支中(使用copy-up模块,如下)并且文件删除通过使用下面两个可用模块其中之一来实现。
WHITEOUT模块,插入一个.wh文件指向一个真实的文件
DELETE_ALL 模块,设法删除所有的分支中的任意一个文件
WHITEOUT模块的默认状态是可用的。Copy-up是一个被用来操作union中的文件修改的特殊模块。只读分支中的文件不能修改,因此在修改时要先把它复制到之前(左边)的可读写分支中。然后修改就可以实现了,并且修改过得文件保存在可读写的分支上。
在上面的例子中最左边增加一个可读写的分支,输入
$unionctl /mnt/union --add --before /mnt/cdrom1 --mode rw /mnt/changes
所有的修改将保存在/mnt/changes中,而union目录就变成如下
/mnt/changes (rw)
/mnt/cdrom1 (r-)
/mnt/cdrom2 (r-)
/mnt/cdrom3 (r-)
真实运用unionfs的实例:SLAX
数据保存在一个只读的媒介如CD-ROM而不能修改。这个linux
livecd发行版支持对所有文件夹可写,这需要使用特殊的技术允许虚拟的修改并把所有的改变保存在内存中。SLAX使用这些技术已经很长时间了,最早是
2003年末使用ovlfs,2004年末将unionfs使用在SLAX
5中,该版本于2005年4月发布,要不是unionfs你不能感受到它所创造的奇迹。
SLAX的内部组织
启动linux需要三个基本的要求:
1) 内核映像(描述操作系统本身的文件,通常叫做vmlinuz);
2) 包括根文件系统和初始化进程(linuxrc)的分区或映像文件(例如initrd.gz);
3) 一些linux引导工具(该工具解压内核映像并将其载入内存)。
SLAX CD启动通过使用isolinux.bin,该引导文件包括了光盘文件系统的驱动程序,并且能够把内核映像(vmlinuz)和根文件系统映像(initrd.gz)从光盘载入内存。
当完成加载内核和运行后,linux内核在电脑的RAM上建立一个虚拟磁盘(称为initrd
ramdisk),并且把initrd.gz解压到其中,同时将其作为根文件系统挂载。SLAX中的initial
ramdisk仅仅有4.4MB大,包含进入SLAX所需的基本软件和驱动程序。最难的是下面的内容,请仔细阅读。
内核执行/linuxrc(ramdisk中)文件作为初始化进程。Linuxrc的工作是相当复杂的。它创建一个空的union目录/union,然后
在/memory目录下挂载空文件系统(即tmpfs),创建目录/memory/changes(这个目录在空文件系统中,而不是在ramdisk
中)。联合文件系统被挂载到/union上,而/memory/changes目录作为一个可读写分支增加到其中。
然后linuxrc通过挂载所有的光盘和磁盘并寻找livecd.sgn文件来找到SLAX
CD。你可能很奇怪,因为cdrom被挂载到/union/mnt/目录下!之后,所有SLAX
CD中必需的映像文件(*.mo)都被挂载在/memory/images/*.mo目录上,并且所有的这些挂载点作为单独的制度分支通过使用
unionctl增加到统一文件系统中,而这些都在第一分支(可读写的changes目录)之后。
/(initrd, 4MB)
|
|---- /memory(tmpfs, 80% of RAM)
| |-- images
| | |-- base.mo <--loop--+
| | | |-- bin |
| | | |-- usr |
| | | +-- var |
| | | |
| | |-- xwindow.mo <-loop------+
| | | |-- etc | |
| | | |-- usr | |
| | | +-- var | |
| | | | |
| | +-- kde.mo <-loop----------+
| | |-- opt | | |
| | |-- usr | | |
| | +-- var | | |
| | | | |
| +-- changes | | |
| | | |
+---- /union | | |
|---- /mnt/cdrom | | |
| |--- base.mo -----+ | |
| |--- xwindow.mo ------+ |
| +--- kde.mo --------------+
+---- /mnt/live
当所有的模块被挂载到union并且可读写分支在union最前面,pivot_root开始运行。这个工作也实现当复杂的,原始的根目录被挂载到
/mnt/live下,而/union将成为新的根目录。在SLAX运行以后可以通过浏览/mnt/live文件夹看到ramdisk的原始内容。
接下来linuxrc执行/sbin/init启动所有的系统服务并且显示登录画面。
值得参考的网址:
(slax 6中用到的文件系统,用来代替unionfs,重点关注。)