对于任何一种操作系统,文件系统都是其最为重要之一环,Linux也不例外。
对于使用惯了Windows的人来说,Linux的文件系统可能也是最难以理解的部分之一了,所以今天要重点讲一下。
那么什么是文件系统呢?简单来说,你有一块硬盘,并通过操作系统去使用它,那么操作系统会在逻辑层面上用一种固定的方式去在这块硬盘上组织数据。之所以说是逻辑层面的东西是因为文件系统这一层与具体如何操作硬盘的驱动程序层是分开的。也就是说,文件系统的实现代码关心的是数据如何组织起来,是逻辑层面的;而驱动程序关心的是如何将每一字节的数据存到硬盘的某一个位置。这种逻辑上的组织方式就是文件系统了。
换言之,文件系统就是一种在存储设备上(譬如硬盘)存储与读取解析数据的协议。
拿我们熟悉的Windows来说吧,Windows的文件系统很简单,将硬盘分为几个分区,分别标上C,D,E等英文字母作为它的标示。其中A,B分给软驱,现在已经不常见了;光盘也标上一个字母;如果你插入了一些即插即用的存储设备,比如U盘,移动硬盘等,也会为它们每一个分区标上一个英文字母。然后每一个分区都采取阶层式树状目录结构,,也就是一个文件夹下面套一个文件夹,看起来像一棵树一样。
然后我们要储存一个名为1.txt的文件在C盘下,Windows就用固定的方式在C盘下建立一个名为1.txt的文件,并将数据存储在硬盘上,还给它分配一个唯一的绝对路径,方便文件的存取,这个路径就是C:1.txt了。
这个就是Windows的文件系统了。也就是Windows组织文件的方式。
这样应该就能理解文件系统是什么了。
那么接下来讲Linux的文件系统了。
下面就是Linux文件系统完整的体系结构,我先不做解释,大家也不用懂,因为我今天基本只讲用户那一层的东东。
首先呢,介绍几个术语,也是概念。
目录,是类UNIX操作系统和DOS下的术语,也就是Windows里的文件夹。
挂载,在Linux下面将一个文件系统和一个存储设备关联起来叫做挂载。
块设备,就是以块(比如磁盘扇区)为单位收发数据的设备,它们支持缓存和随机读取,比如硬盘,CD等等。
介绍完术语接下来是详细讲解。
首先Linux也采用的是阶层式树状目录结构(别以为树状目录结构是天经地义的,这个是UNIX的发明,UNIX同时代或者稍后一点的操作系统都是没有目录概念的,所有文件放在一起,包括在DOS之前统治PC的CP/M操作系统)。
但是Linux和Windows不一样,它有一个VFS也就是虚拟文件系统(Virtual File System),再上一张图里面有一个节点缓存和目录缓存,就是VFS的一部分了。为什么说是虚拟文件系统呢?这点就和Windows大不一样了。Windows是将目录结构完完全全存储在硬盘上的,读取的时候从硬盘读取,修改的时候直接修改硬盘。而Linux不一样,它有一个虚拟的目录表,其中一部分是存储在硬盘上的,一部分储存在内存里,为什么要这样,我接下来会讲。
Linux文件系统的最上层是 / ,被称为根目录,也就是一个目录树的树根。然后其下可以建立其它的目录。
与Windows不同,Linux有严格的目录使用规定,不同目录用来干不同的事。而Windows其实也有,都在C盘里,只不过都一切帮你包办了…………
接下来介绍每个目录的作用,大家可以和自己的Linux对照一下。
/ :不用说了,根目录,所有目录的起点。
/bin :binary的缩写,顾名思义了,也就是存放二进制文件的地方,一般放一些所有用户都用的,不影响系统的基本程序,也就是基础系统的基础命令。
/boot :这个意义更明显了,就是存放引导文件的地方。还有GRUB和LILO(都是Linux的启动管理器)也放在这。
/dev :设备文件的目录。
/etc :放系统配置文件的地方。
/home :普通用户的目录,一般没有特殊情况会在这个目录下建立一个以用户名为名字的目录,普通用户只能操作这个目录的东西,系统目录只有root能够操作。
/lib :library的缩写,存放库文件,也就是一系列的函数库。
/mnt :挂载文件系统的地方,一般会建立一个子目录(Fedora发行版使用的是/media)
/opt :optional的缩写,表示可以选择,有些自定义软件包会安装在这,供较大而且固定的应用程序存放文件。
/proc :procedure的缩写,存放进程信息,硬件信息,内核信息的地方。
/root :root用户的主目录。
/sbin :大多数系统管理程序的存放地,一般只有root用户才能执行(shutdown就在这下面,普通用户的PATH环境变量可能不包括这个目录)。
/tmp :存放临时文件的地方,还有Slackware的SlackBuild会使用这个目录。
/usr :存放程序的目录,一般存放非系统应用程序,在这下面也有etc等子目录存放普通应用程序的配置文件。user的缩写,就是存放用户后来安装的程序的地方了。一般系统安装后安装的软件都在这。
/var :一个经常变动的目录,作用很多,一时也讲不清楚了…………
解释了各个目录的作用后,就要讲解普通人最难以理解也是Linux最具有魅力的东西了,那就是VFS。
看了那么多讲解,细心一点的人可能会问,Linux是不是不分区的啊?
乍看是的,所有的东西都放在根目录底下。但是实际上并非如此。
所有的类UNIX操作系统都使用这种VFS的机制。
我之前介绍过一个术语,挂载,将一个文件系统和一个存储设备关联起来。Linux是使用挂载的。也就是你可以将硬盘上的任何一个分区挂载到Linux的任何一个目录上,然后就可以通过那个目录访问这个设备了。
为什么要这样呢?因为UNIX有一个统一性思想:一切皆文件(包括目录,也是一种特殊的文件)。
Linux将整个文件系统树存储在内存里,就是那个目录缓存。挂载就是将这个文件系统树上的一个目录与一个设备连接起来。要知道,/ 、/dev、/proc、都不是硬盘上实际存在的目录,而是Linux在内存中虚构出来的,所以叫做虚拟文件系统。
Linux将一切的硬件都化为一个文件存储在/dev目录中。比如说你的IDE硬盘以hda,hdb等名字储存,SATA硬盘则以sda,sdb等名字存储,终端设备(可以理解为屏幕)以tty这个名字存储,甚至打印机、网卡等一切的硬件设备都会在/dev中有一个对应的文件。
然后对于一个硬盘上的分区,比如sda这块硬盘的分区,Linux会将每一个分区给一个数字标示,比如第一个分区叫sda1,第二个是sda2…………依次类推。你要使用这个分区了就将sda1与一个目录对应起来,将sda2与另一个目录对应起来。比如说我将/dev/sda1挂载到/mnt/win7上,那么你就可以通过访问/mnt/win7来访问这个分区的数据了,非常方便。
现在许多Linux的发行版都会提供自动挂载,不用我们手动挂载Windows的分区了。
那么这样有什么好处呢?
好处就在于用户不用关心设备层面的具体操作就可以使用相应的硬件了。
比如我们在Linux使用C编程,通常会使用Linux的系统调用。举例说,有一个系统调用叫write,顾名思义,功能就是写入。它可以将数据写入一个已经打开的文件。如果是普通的文件可以理解,那如果打印机也是一个文件呢?你用write向对应打印机的那个文件写入数据,不就是在打印机上打印了吗?同理,你向一个代表屏幕的文件写入数据,不就代表在屏幕上输出了吗?
好了,点到为止。
通过这种手段,所有的硬件对于用户而言都可以看成文件,那我们就可以用同一种手段去操纵它。不然,想使用打印机了,打印机有它的读写方式;想读写屏幕了,屏幕又有它的读写方式;想读写硬盘了,硬盘又有它的读写方式…………你要记住多少才够呢?
这样,一切的硬件都简化为文件了,只要你装了驱动程序,你不用关心如何去操作硬件了,所有的硬件都可以使用标准的系统调用解决,这不是很easy,很happy的事吗?
还有那个/proc目录,这也不是实际存储在硬盘上的,而是存储在内存里的。它将所有的硬件信息,进程信息,内核信息都转变为普通的文本文件,这样我们可以毫无障碍地去了解这些信息,因为它们都是普通的文本文件啊。
比如说你想要知道一个进程的信息只要读取相关的文件就可以了,不是很简单吗?
这样你在编程的时候,怎么了解硬件信息呢?不用去记那种又艰涩又长的API只要用read系统调用读取/proc目录下的信息就可以了,不是很简单吗?
所以,Linux也是一个开发者友好型的系统啊。当你熟悉了之后,就会对Windows下的编程方式深恶痛疾了。
这就是我上一节提到的UNIX的KISS准则的一个体现啊。
好了,当你在这里有了顿悟,那么你就理解了Linux的文件系统了。
记住,Linux(其实是UNIX)的一个统一性原理————一切皆文件。
看到这里,你可能觉得Linux的文件系统看起来很复杂,其实不然。Linux有一切皆文件的统一性原理,当你懂得了之后,你会发现Linux的文件系统其实比Windows不知道简洁到哪里去了————因为在Linux中一切都是文件,没有任何的特例,不用记住任何例外的东西,而Windows则处处是特例啊。
要知道,大家之所以认为Windows简单是因为习惯于Windows了,而其实Linux是更简单的!