《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)

1.1文件系统概述

1.1.1文件系统的类型

1)磁盘文件系统
Ext4/Ext3为Linux系统的广泛格式;
FAT16,FAT32为Windows系统的广泛格式。

2)网络文件系统

3)虚拟/专用文件系统
Linux文件类型(细分)

普通文件:- //指定二进制文件
块设备文件:b//块输入输出文件
字符设备文件:c//原始输入输出文件
目录文件:d//包含若干文件与目录
符号链表文件:l//只包含文件地址,不包含文件本身
命令管道:p//一种通信的机制
套接字:s//进程间的通信机制

1.1.2 Linux文件系统的类型

在UNIX/Linux系统中,文件分为三类:即普通文件、目录文件和特殊文件。
1.普通文件
也称正文文件,可以用来保存程序、数据等任何信息。这是一种无结构的,以512个字节为一块,顺序存取的流式文件。

2.目录文件
用于检索文件的文件。目录文件可能是系统文件,也可能是用户文件。

3.特殊文件
即设备。在UNIX系统中将设备也作为文件来处理,对于设备的所有操作都需要经过文件系统。这有如下两个优点:

  • 设备与文件界面统一:使用设备与使用文件没有差别. 具体地说, 打开一个设备文件相当于申请该设备,关闭一个设备文件相当于释放该设备,读写设备文件相当于对设备进行I/O操作。

  • 2设备可采用与文件相同的保护机制:文件可以访问权限等手段加以保护, 设备作为文件处理也可如同文件一样得到保护. 如对于打印机设备可规定为只“写”型设备,对其实行“读”操作将被视为非法而加以拒绝。将设备作为特殊文件管理是UNIX系统的成功特点之一,并被后来其它一些操作系统所借鉴。

1.1.1 Linux文件系统的类型

在UNIX系统中,文件分为三类: 即普通文件、目录文件和特殊文件。

1.普通文件
也称正文文件,可以用来保存程序、数据等任何信息。这是一种无结构的,以512个字节为一块,顺序存取的流式文件。

2.目录文件
用于检索文件的文件。目录文件可能是系统文件,也可能是用户文件。

3.特殊文件
即设备。在UNIX系统中将设备也作为文件来处理,对于设备的所有操作都需要经过文件系统。这有如下两个优点:
A.设备与文件界面统一:使用设备与使用文件没有差别. 具体地说, 打开一个设备文件相当于申请该设备,关闭一个设备文件相当于释放该设备,读写设备文件相当于对设备进行I/O操作。

B.设备可采用与文件相同的保护机制:文件可以访问权限等手段加以保护, 设备作为文件处理也可如同文件一样得到保护. 如对于打印机设备可规定为只“写”型设备,对其实行“读”操作将被视为非法而加以拒绝。将设备作为特殊文件管理是UNIX系统的成功特点之一,并被后来其它一些操作系统所借鉴。

1.2文件体系

UNIX文件系统呈树形结构, 树的根结点为根目录root, 树的叶结点可以为普通文件、特殊文件、或者目录文件. 其它既非根结点也非叶结点的结点为目录文件。如图 1所示。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第1张图片

图1

图中虚线代表链接(link),通过链接可以给一个文件赋予多个符号名(路径名),这是共享文件的一种方法。

具体的目录结构:

 /bin [重点] (/usr/bin 、 /usr/local/bin)
• 是Binary的缩写, 这个目录存放着最经常使用的命令。

 /sbin (/usr/sbin 、 /usr/local/sbin)
• s就是Super User的意思,这里存放的是系统管理员使用的系统管理程序

 /home [重点]
• 存放普通用户的主目录,在Linux中每个用户都有一个自己的目录,一般该目录名是以用户的账号命名的。

 /root [重点]
• 该目录为系统管理员,也称作超级权限者的用户主目录。

 /lib
• 系统开机所需要最基本的动态连接共享库,其作用类似于Windows里的DLL文件。几乎所有的应用程序都需要用到这些共享库。

 /lost+found
• 这个目录一般情况下是空的,当系统非法关机后,这里就存放了一些文件。

 /etc [重点]
• 所有的系统管理所需要的配置文件和子目录 my.conf

 /usr [重点]
• 这是一个非常重要的目录,用户的很多应用程序和文件都放在这个目录下,类似与windows下的program files目录。

 /boot [重点]
• 存放的是启动Linux时使用的一些核心文件,包括一些连接文件以及镜像文件。

 /proc
• 这个目录是一个虚拟的目录,它是系统内存的映射,访问这个目录来获取系统信息。

 /srv
• service缩写,该目录存放一些服务启动之后需要提取的数据。

 /sys
• 这是linux2.6内核的一个很大的变化。该目录下安装了2.6内核中新出现的一个文件系统。

 /tmp
• 这个目录是用来存放一些临时文件的。

 /dev
• 类似于windows的设备管理器,把所有的硬件用文件的形式存储。

 /media [重点]
• linux系统会自动识别一些设备,例如U盘、光驱等等,当识别后, linux会把识别的设备挂载到这个目录下。

 /mnt [重点]
• 系统提供该目录是为了让用户临时挂载别的文件系统的,我们可以将外部的存储挂载在/mnt/上,然后进入该目录就可以查看里的内容了。 d:/share

 /opt
• 这是给主机额外安装软件所摆放的目录。如安装ORACLE数据库就可放到该目录下。默认为空。

 /usr/local [重点]
• 这是另一个给主机额外安装软件所安装的目录。一般是通过编译源码方式安装的程序。

 /var [重点]
• 这个目录中存放着在不断扩充着的东西,习惯将经常被修改的目录放在这个目录下。包括各种日志文件。

 /selinux [security-enhanced linux]
• SELinux是一种安全子系统,它能控制程序只能访问特定文件。

文献:http://www.pathname.com/fhs/

下面我们就最重要的目录进行详细讲解。

1.2.1 /sys目录

在ubuntu12.04的sys目录下,可以通过tree查看该目录结构。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第2张图片

图2

首先,对 /sys目录下的各个子目录进行具体说明:

/sys/devices
该目录下是全局设备结构体系,包含所有被发现的注册在各种总线上的各种物理设备。一般来说,所有的物理设备都按其在总线上的拓扑结构来显示,但有两个例外,即platform devices和system devices。platform devices一般是挂在芯片内部的高速或者低速总线上的各种控制器和外设,它们能被CPU直接寻址;system devices不是外设,而是芯片内部的核心结构,比如CPU,timer等,它们一般没有相关的驱动,但是会有一些体系结构相关的代码来配置它们(sys/devices是内核对系统中所有设备的分层次表达模型,也是/sys文件系统管理设备的最重要的目录结构)。

sys/dev
该目录下维护一个按照字符设备和块设备的主次号码(major:minor)链接到真是设备(/sys/devices)的符号链接文件。

/sys/class
该目录下包含所有注册在kernel里面的设备类型,这是按照设备功能分类的设备模型,每个设备类型表达具有一种功能的设备。每个设备类型子目录下都是这种哦哦那个设备类型的各种具体设备的符号链接,这些链接指向/sys/devices/name下的具体设备。设备类型和设备并没有一一对应的关系,一个物理设备可能具备多种设备类型;一个设备类型只表达具有一种功能的设备,比如:系统所有输入设备都会出现在/sys/class/input之下,而不论它们是以何种总线连接到系统的(/sys/class也是构成linux统一设备模型的一部分)。

/sys/block
该目录下的所有子目录代表着系统中当前被发现的所有块设备。按照功能来说防止在/sys/class下会更合适,但由于历史遗留因素而一直存在于/sys/block,但从linux2.6.22内核开始这部分就已经标记为过去时,只有打开了CONFIG_SYSFS_DEPRECATED配置编译才会有这个目录存在,并且其中的内容在从linux2.6.26版本开始已经正式移到了/sys/class/block,旧的接口/sys/block为了向后兼容而保留存在,但其中的内容已经变为了指向它们在/sys/devices/中真实设备的符号链接文件。

/sys/bus
该目录下的每个子目录都是kernel支持并且已经注册了的总线类型。这是内核设备按照总线类型分层放置的目录结构,/sys/devices中的所有设备都是连接于某种总线之下的,bus子目录下的每种具体总线之下可以找到每个具体设备的符号链接,一般来说每个子目录(总线类型)下包含两个子目录,一个是devices,另一个是drivers;其中devices下是这个总线类型下的所有设备,这些设备都是符号链接,它们分别指向真正的设备(/sys/devices/name/下);而drivers下是所有注册在这个总线上的驱动,每个driver子目录下 是一些可以观察和修改的driver参数(它也是构成linux统一设备模型的一部分)。

/sys/fs
按照设计,该目录使用来描述系统中所有的文件系统,包括文件系统本身和按照文件系统分类存放的已挂载点。

/sys/kernel
这个目录下存放的是内核中所有可调整的参数。

/sys/firmware
该目录下包含对固件对象(firmware object)和属性进行操作和观察的接口,即这里是系统加载固件机制的对用户空间的接口(关于固件有专用于固件加载的一套API)。

/sys/hypervisor
该目录是与虚拟化Xen相关的装置(Xen是一个开放源代码的虚拟机监视器)。

/sys/module
该目录下有系统中所有的模块信息,不论这些模块是以内联(inlined)方式编译到内核映像文件中还是编译为外模块(.ko文件),都可能出现在/sys/module中。即module目录下包含了所有的被载入kernel的模块。

/sys/power
该目录是系统中的电源选项,对正在使用的power子系统的描述。这个目录下有几个属性文件可以用于控制整个机器的电源状态,如可以向其中写入控制命令让机器关机/重启等等。
可以看到 sys 下的目录结构是经过精心设计的:在/sys/devices 下是所有设备的真实对象,包括如视频卡和以太网卡等真实的设备,也包括ACPI 等不那么显而易见的真实设备、还有tty, bonding 等纯粹虚拟的设备;在其它目录如 class, bus 等中则在分类的目录中含有大量对 devices 中真实对象引用的符号链接文件。

1.2.2 /bin、/sbin、/usr/bin、/usr/sbin目录的区别

在linux下我们经常用到的四个应用程序的目录是/bin、/sbin、/usr/bin、/usr/sbin 。
而四者存放的文件一般如下:

/bin:
bin为binary的简写主要放置一些系统的必备执行档
例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar等。
这里的mount大家要注意,在/sbin目录下也有,注意区别。

/usr/bin:
主要放置一些应用软件工具的必备执行档。
例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome*、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb*、wget等。

/sbin:
主要放置一些系统管理的必备程序,可以这样理解,就是在普通用户下要加sudo获取到超级用户权限才可以执行的。
例如:cfdisk、dhcpcd、dump、e2fsck、fdisk、halt、ifconfig、ifup、 ifdown、init、insmod、lilo、lsmod、mke2fs、modprobe、quotacheck、reboot、rmmod、 runlevel、shutdown等。

/usr/sbin:
放置一些网路管理的必备程序。
例如:dhcpd、httpd、imap、in.*d、inetd、lpd、named、netconfig、nmbd、samba、sendmail、squid、swap、tcpd、tcpdump等

综述:如果这是用户和管理员必备的二进制文件,就会放在/bin。如果这是系统管理员必备,但是一般用户根本不会用到的二进制文件,就会放在 /sbin。相对而言。如果不是用户必备的二进制文件,多半会放在/usr/bin;如果不是系统管理员必备的工具,多半会放在/usr/sbin。

如果新装的系统,运行一些很正常的诸如:shutdown,fdisk的命令时,悍然提示:bash:command not found。那么首先就要考虑root 的$PATH里是否已经包含了这些环境变量。

可以查看PATH,如果是:PATH=$PATH:$HOME/bin则需要添加成如下:
PATH=$PATH:$HOME/bin:/sbin:/usr/bin:/usr/sbin

附:根目录
/ (这就是著名的根)
├── bin (你在终端运行的大多数程序,比如cp、mv…)
├── boot (内核放在这里,这个目录也经常被作为某个独立分区的挂载点)
│ └── grub (grub引导程序和引导菜单就放在这里)
├── cdrom
├── dev (存放设备文件,这里相当于一个设备管理器,由系统自动生成。视硬件环境不同变化很大)
│ ├── block
│ ├── bsg
│ ├── bus
│ ├── char
│ ├── disk (磁盘信息,要挂载硬盘分区就要注意这里的信息喽)
│ │ ├── by-id (硬盘分区的永久性符号链接)
│ │ ├── by-label (按卷标识别的硬盘分区,常用于挂载)
│ │ ├── by-path (硬盘分区的节点链接)
│ │ └── by-uuid (按UUID识别的硬盘分区,常用于挂载)
│ ├── dri
│ ├── fd
│ ├── input
│ ├── net
│ ├── pts
│ ├── shm
│ └── snd
├── etc (存放所有程序和系统的配制文件和全局变量,对所有用户生效,非常值得备份)
├── home (这就是著名的home目录了,注意不是”家目录”,强烈建议把一个独立分区挂载到这里!)
│ ├── adagio (这才是我真正的家!一般来说目录名就是帐号名,当然也可以不是,随便。命令行中用波浪线~代表这里)
│ ├── MNT (这是我挂载其它硬盘分区的地方,你可以看到用硬盘品牌、容量或用途区分的目录名)
│ │ ├── MAX40NT1 (迈拓40G)
│ │ ├── ST160NT1 (希捷160G第一分区,下面两个类似)
│ │ ├── ST160NT2
│ │ ├── ST160SYS
│ │ ├── ST320G (希捷320G)
│ │ │ ├── MOVIE
│ │ │ ├── MUSIC
│ │ │ └── P2P (电驴、BT的缓冲区)
│ │ ├── ST80G (希捷80G)
│ │ │ ├── PROGRAM
│ │ │ ├── ST80PE
│ │ │ └── YEAR
│ │ └── WD1000 (西数1T)
│ │ ├── WD2
│ │ ├── WD3
│ │ ├── WD5
│ │ ├── WD6.Lib
│ │ └── WD7
│ └── test (我建立的另一个帐号的家目录,专门用于测试,一旦搞到无法收拾的地步,只需简单的把里面的所有文件删除,就可以恢复默认。实际上你可以拥有无数个帐号)
├── lib (所有程序共享的库文件)
├── lost+found (磁盘扫描出现的丢失的数据)
├── media (你在文件管理器里点击后自动挂载的分区就在这里,按卷标命名,没有卷标则按大小命名)
├── mnt (同样用于挂载磁盘,这是最传统的位置,喜欢挂哪里随便)
├── opt (某些特殊的程序喜欢把数据放在这里,比如JAVA)
├── proc (当前系统所有的详细信息,这里的”文件”并不存在于硬盘中,而是在内存或缓存里,每次启动后都不一样)
├── root (这是系统最高权威root用户的家!他是老大,所以不住在/home里,那里是草民住的)
├── sbin (类似/bin,存放常用程序,但这里的程序都是要命的啊,比如格式化,所以只有root用户或sudo程序有权使用)
├── srv (一些服务所要访问的文件)
├── sys (系统的核心文件,类似/proc,不必管它)
├── tmp (存放临时文件,所有用户均可使用,不过你要小心啊,这里的所有文件一旦重启就全没了,自动清空的)
├── usr (你在X下使用的所有程序数据都在这里了,包括图标、manual等。所有用户都可以使用。也是最庞大的目录)
└── var (variation,顾名思义就是变量,这里存放系统中经常变化的数据。和/tmp不同啊,很有用的地方)
├── backups
├── cache
│ └── apt
│ └── archives (存放你安装的所有程序的deb包!重装系统时太有用了,一定要备份好,到时候放回来。 我建议把整儿/var单独挂载到一个独立分区,像/home一样。这样你重装好系统后,只需要简单的把整儿分区挂载到/var就行了,省去了备份-还原的时间。要知道这些deb包可不是几十M而已,而是有可能几百M、几个G,一来一回可够呛的。你也可以单独挂载个分区到/var/cache/apt/archives,其他的都不要。当然,这样又增加了一点系统构造的复杂度,喜欢怎样请自己斟酌。)
├── crash
├── games
├── lib
├── local
├── lock
├── log (这里的文件是系统运行的完整记录,出了问题一定要来这里看看)
├── mail (这里是存放所有用户email的地方)
├── opt
├── run
├── spool
└── tmp

设备树安装
一般情况下,设备树查看器未安装,安装设备树显示命令:
sudo apt-get install tree

1.3文件结构

1.文件的逻辑结构
UNIX普通文件的逻辑结构为流式的。在用户看来, 一个文件是一个字节序列。文件的读写操作命令包含传输字节的个数。这种结构实现简单,系统开销小。当然, 如果需要,用户可以利用流式文件来构造记录式文件,因为对于文件内容的解释权完全留给了用户。

2.文件的物理结构

UNIX文件的物理结构为链接结构与索引结构的结合, 也可看成是多级索引结构。其实现如图2所示。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第3张图片

图3

1.4文件目录与连接

1.目录项
相当于FCB次部,包括两个内容: 即文件名和inode编号, 不同的文件名可能对应同一个inode编号, 这样便对应同一个FCB主部, 即一个文件可以有多个名字.

2. inode
相当于FCB主部, 包括文件主、共享说明、地址信息等,称为inode, inode与文件具有一对一的关系. 在UNIX文件系统中,有一个固定的区域,用于保存所有文件的inode. 如图3所示. 每个inode有一个唯一的编号,称为i_number。

这里写图片描述

图4

将FCB分为两部分的目的之一是实现文件的连接,所谓连接实际是使多个目录项与同一个inode建立联系,从而可以通过不同的路径名查找到同一个文件,即使一个文件有多个符号名称. 例如对于图4(a)所示的目录树,经过连接后文件f增加了路径名/usr/Xu/d2/g,如图4(b)所示.二者具有相同的i_number(15),因而对应同一个inode。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第4张图片

图5

1.5文件系统映射

文件打开时,控制信息被移入内存相关表目中,并通过文件描述符建立与文件内容之间的联系.

图6给出了进程空间与u_ofile表、file表、inode表之间的连接关系,其中文件描述符4,6对应两个不同的文件,描述符10,2对应同一文件但不共享读写指针,描述符8,9对应同一文件且共享读写指针。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第5张图片

图6

完整的file结构定义如下:

struct file
 {
char  f_flag;      /* FREAD=01, FWRITE=02, FPIPE=04 */
char  f_count;    /* reference count */
int   f_inode;     /* pointer to inode structure */
char  *f_offset;  /* read/write character pointer */
}

1.6文件卷的安装

用一个文件卷的根目录取代文件的一个普通文件。这样一个文件卷可以动态地联结到文件系统中, 也可以动态地由文件系统中卸下。文件卷的组织形式如图7所示。 其中块#0为引导块, 负责操作系统的装入; 块#1为特殊块, 记载磁盘块的分配状况; 由块#2到块#k+1为inode区域, 保存文件FCB主部, 其k值在文件卷初始化时确定; 由块#k+2到块#n-1为一般块, 保存普通文件及目录文件的内容。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第6张图片

图7

其中引导块只对系统根文件卷才是有意义的,它负责在系统启动时在磁盘上找到UNIX系统并将其装入内存. 超级块(super block)是一个文件卷中最重要的数据结构,它记录本卷上inode块和一般块的分配状况,以及锁等标志信息。

文件的变化(建立、撤销、写入等)一般都需要访问超级块以实现对inode块和一般块的管理。 文件卷卸下(unmount)时,若超级块在内存期间被修改,则需要写回外存。 实际上,这种回写每隔一段时间都需要执行一次,以防止意外,保证缓冲区内容与文件卷内容的一致性。

1.7磁盘空间管理

UNIX空闲磁盘空间的管理采用了成组连接方式,它可看成是空闲块链与空闲块表的结合,涉及超级块(块号#1)中s_nfree,s_free[100]和s_flock三个数据结构. s_free可记录多达100个空闲块号以及一个由连接块构成的成组连接链之链头, 而每个连接块中登记有多达100个空闲块号以及一个指向下一个连接块的指针;s_nfree是当前超级块中所记录的空闲块的个数;s_flock是互斥操作空闲块数据结构的锁标志. 如图8所示。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第7张图片

图8

1.8 inode区域管理

inode区中保持文件控制块的主部,对于第六版UNIX,一个inode占32个字节,一个磁盘块长度为512字节,这样一块中可以保存16个inode。 将inode区中所有inode由0开始依次编号,称为i_number,i_number是inode的唯一标识,也是文件的唯一标识。在inode中包含i_nlink,i_nlink=0者为空闲inode。

filesys中与inode管理相关数据结构包括s_ninode, s_inode和s_ilock. 其中s_inode可记录多达100个空闲inode的编号。申请时,取s_inode[–s_ninode],当s_ninode=0时缓冲区中记录的空闲inode已经全部用完,此时顺序扫描inode区寻找100个空闲inode(i_nlink= =0),并将其编号记录到s_inode中。 释放时,执行s_inode[s_ninode++]=释放inode编号,当s_ninode==100时,丢弃该inode编号。

文件的inode长期保存在磁盘上,当文件被打开时,inode被缓冲到内存以提高存取速度。 内存中的inode与外存中的inode应当保持一致,当内存中inode 发生变化时应及时将其写回外存,具体回写时刻有三种情况:(1)文件关闭;(2)定时更新;(3)执行。

其中i_mode为各种标志信息,低9位为访问权限,其它各位含义如8所示,其中置uid位若为1且该文件为可执行文件,则执行该程序的进程其uid暂时改为文件主的uid。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第8张图片

图9

其中i_flag为标志位,内容包括互斥锁、修改位、访问位、安装标识、等待标志等,如图9所示。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第9张图片

图10

1.9 快速文件系统(Fast File System)

经典UNIX文件系统在设计方面是非常成功的,然而随着磁盘容量和文件长度的增加也显现出一些问题。

(1)首先UNIX文件卷将inode区与内容存储区相互分离,当查找一个较长的路径名时需要由inode区到内容存储区,再由内容存储区到inode区几次往复,对应磁头引臂在内外磁道的频繁运动。

(2)其次长度为512字节的磁盘块尺寸过小,对于稍长的文件就意味着I/O块间址,I/O效率低。

(3)另外长度为14字节的文件名分量也是一个苛刻的限制。

为克服经典UNIX文件系统的局限性,UC Berkeley提出了一种成为快速文件系统(Fast File System)的改进策略,这种改进使其效率提高一个数量级,目前已被用于大多数UNIX版本中,其中包括4.2BSD等。

首先, FFS将磁盘卷划分为若干个柱面组(cylinder group),每个柱面组占若干连续的柱面,作为相对独立的文件卷管理,其中包含各自独立的超级块、inode区和数据块,如图11所示。文件路径名中所涉及的分量,以及一个文件的所有磁盘块都局部在同一柱面组内,大大减小了inode区与数据块区之间的物理距离。其中数据块被分散在柱面组的两端,进一步减小由inode区到数据块区的磁头移动量。在核心级别,系统通过二元组<逻辑设备号,inode号>来识别一个文件。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第10张图片

图11

其次,FFS采用较大的磁盘块以减少I/O间址并提高I/O效率。磁盘块的尺寸可达8k,这样对于长度为80k的文件不需间址,10次I/O传输即可全部读入内存。对于没有间接块的文件,4.2BSD采用大小两种块尺寸:除最后一块外,一个文件所有其它块均为大块(如8k),而最后一块为1k的整数倍,称为片(fragment).

1.10 NFS网络文件系统

包括SunOS(UNIX 4.2BSD),NFS已被所有现代UNIX系统所采用,成为目前最有影响的远程文件访问系统。在逻辑结构上位于NFS之上的虚拟文件系统VFS(Virtual File System)最初只是针对NFS而设置的,用于识别本地与远程文件访问,但现在VFS已支持多种不同的本地文件系统,成为UNIX文件系统的统一界面。

1.10.1 NFS体系结构

每个服务员可输出(export)一个或多个目录以供远程客户共享,被共享目录所属的子树亦被共享。服务员输出的共享目录记载在/etc/export文件中。客户通过安装(mount)命令实现对目录的共享,被安装的目录成为其目录层次的组成部分。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第11张图片

图12

1.10.2 协议

由于NFS的目标是支持异构系统,客户和服务员可以处于不同操作系统平台和硬件环境中,定义两个协议。

(1)远程安装协议,不透明的;
(2)远程存取协议,透明的。

远程安装协议用于建立客户与服务器之间的逻辑联系,服务器端export可以被远程安装的目录名以及允许安装的机器,需要给出:(a)远程待安装目录的路径命名;(b)远程机器名。远程安装命令被NFS映射到对应的RPC调用,经过网络传输到服务器,客户可以向服务器发送一个请求,将服务器上某一目录安装到顾客端指定目录.返回描述符.安装协议是不透明的,需要给出机器名称,这使NFS不是真正的分布式文件系统。

远程存取协议提供一套RPC调用,执行如下操作:

(1)查找目录下的文件;
(2)读取目录项目;
(3)操作link与目录;
(4)存取文件属性;
(5)读写文件. 远程存取协议是透明的,与操作本地目录和文件相同.
NFS是无状态的(stateless):文件服务端并不在内存打开文件表中保持文件控制信息,为此每个文件操作命令必须是自包含的(self contained),即必须提供完整的参数集合。另外NFS不提供并发控制机制。

1.10.3 NFS实现

客户端VFS功能:
(1)识别本地文件与远程文件,对于远程文件,调用NFS协议过程;
(2)对于本地文件,区分本地文件系统类型,并根据文件类型激活相应文件操作。

服务器端VFS功能:实现NFS协议,接受来自客户端的调用并将其传递给本地FS. 客户端与服务器端均由若干层次构成,如图12所示。

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第12张图片

图13

对远程文件的操作映射过程如下:

(1)客户端通过系统调用发出访问请求;
(2)操作系统将其映射到对应vnode的一个VFS操作;
(3)VFS层鉴别为远程文件,调用NFS对应的过程;
(4)NFS向远程服务器发出RPC调用;
(5)远程服务器识别为本地文件,启用对应的文件操作;
(6)按相同路径将调用结果由服务器反向传给顾客。

1.11符号链接(软链接)和硬链接的区别

可以用ln命令对一个已经存在的文件建立一个新的连接,而不复制文件的内容。连接有软连接和硬连接之分,软连接又叫符号连接。
符号链接是指向一个文件的间接指针,硬链接直接指向文件的i节点。

表1

《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础)_第13张图片

你可能感兴趣的:(《Linux操作系统 - 高级编程》第一部分 标准IO及文件IO(第1章 UNIX文件基础))