文件属性与目录

一、Linux 系统中的文件类型 Linux 系统中的文件类型

Linux 下一切皆文件,文件作为 Linux 系统设计思想的核心理念。

1、普通文件  

普通文件( regular file )在 Linux 系统下是最常见的,譬如文本文件、二进制文件,我们编写的源代码文件这些都是普通文件,也就是一般意义上的文件。普通文件中的数据存在系统磁盘中,可以访问文件中的内容,文件中的内容以字节为单位进行存储于访问。
⚫ 文本文件: 文件中的内容是由文本构成的,所谓文本指的是 ASCII 码字符。文件中的内容其本质上都是数字(因为计算机本身只有 0 和 1 ,存储在磁盘上的文件内容也都是由 0 和 1 所构成),而文本文件中的数字应该被理解为这个数字所对应的 ASCII 字符码;譬如常见的 .c 、 .h 、 .sh 、 .txt 等 这些都是文本文件,文本文件的好处就是方便人阅读、浏览以及编写。
⚫ 二进制文件: 二进制文件中存储的本质上也是数字,只不过对于二进制文件来说,这些数字并不是文本字符编码,而是真正的数字。譬如 Linux 系统下的可执行文件、 C 代码编译之后得到的 .o 文件、.bin 文件等都是二进制文件。

Linux 系统下,可以通过 stat 命令或者 ls 命令来查看文件类型,如下所示:

stat 命令非常友好,会直观把文件类型显示出来;对于 ls 命令来说,并没有直观的显示出文件的类型, 而是通过符号表示出来,在图 5.1.2 中画红色框位置显示出的一串字符中,其中第一个字符 ' - ' )就用于表 示文件的类型,减号' - ' 就表示该文件是一个普通文件;除此之外,来看看其它文件类型使用什么字符表示:
' - ' :普通文件
' d ' :目录文件
' c ' :字符设备文件
' b ' :块设备文件
' l ' :符号链接文件
' s ' :套接字文件
' p ' :管道文件

2、目录文件

目录( directory )就是文件夹,文件夹在 Linux 系统中也是一种文件,是一种特殊文件,同样我们也可以使用vi 编辑器来打开文件夹。在 Linux 系统下,会有一些专门的系统调用用于读写文件夹
⚫ 普通文件由 inode 节点和数据块构成
⚫ 目录由 inode 节点和目录块构成

3、字符设备文件和块文件

Linux 系统下,一切皆文件,也包括各种硬件设备。设备文件(字符设备文件、块设备文件)对应的是硬件设备,在 Linux 系统中,硬件设备会对应到一个设备文件,应用程序通过对设备文件的读写来操控、使用硬件设备,譬如 LCD 显示屏、串口、音频、按键等。


虽然有设备文件,但是设备文件并不对应磁盘上的一个文件,也就是说设备文件并不存在于磁盘中, 而是由文件系统虚拟出来的,一般是由内存来维护,当系统关机时,设备文件都会消失;字符设备文件一般存放在 Linux 系统 /dev/ 目录下,所以 /dev 也称为虚拟文件系统 devfs


4、符号链接文件

符号链接文件( link )类似于 Windows 系统中的快捷方式文件,是一种特殊文件,它的内容指向的是另 一个文件路径,当对符号链接文件进行操作时,系统根据情况会对这个操作转移到它指向的文件上去,而不是对它本身进行操作,譬如,读取一个符号链接文件内容时,实际上读到的是它指向的文件的内容。


5、管道文件

管道文件( pipe )主要用于进程间通信


6、套接字文件

套接字文件( socket )也是一种进程间通信的方式,与管道文件不同的是,它们可以在不同主机上的进 程间通信,实际上就是网络通信。


总结:

普通文件是最常见的文件类型;
目录也是一种文件类型;
设备文件对应于硬件设备;
符号链接文件类似于 Windows 的快捷方式;
管道文件用于进程间通信;
套接字文件用于网络通信。

二、stat函数

Linux 下可以使用 stat 命令查看文件的属性,其实这个命令内部就是通过调用 stat() 函数来获取文件属性的,stat 函数是 Linux 中的系统调用,用于获取文件相关的信息。

三、fstat lstat 函数

除了 stat 函数之外,还可以使用 fstat lstat 两个系统调用来获取文件属性信息。fstat lstat stat 的作用一样,但是参数、细节方面有些许不同。
fstat stat 区别在于, stat 是从文件名出发得到文件属性信息,不需要先打开文件;而 fstat 函数则是从文件描述符出发得到文件属性信息,所以使用 fstat 函数之前需要先打开文件得到文件描述符。

四、文件属主

Linux 是一个多用户操作系统,系统中一般存在着好几个不同的用户,而 Linux 系统中的每一个文件都有一个与之相关联的用户和用户组,通过这个信息可以判断文件的所有者和所属组。
文件所属组则表示该文件属于哪一个用户组。在 Linux 中,系统并不是通过用户名或用户组名来识别不同的用户和用户组,而是通过 ID ID 就是一个编号, Linux 系统会为每一个用户或用户组分配一个 ID ,将 用户名或用户组名与对应的 ID 关联起来,所以系统通过用户 ID UID )或组 ID GID )就可以识别出不同 的用户和用户组。
譬如使用 ls 命令或 stat 命令便可以查看到文件的所有者和所属组,如下所示:

chown 函数

chown 是一个系统调用,该系统调用可用于改变文件的所有者(用户 ID )和所属组(组 ID )。
虽然该函数用法很简单,但是有以下两个限制条件:
只有超级用户进程能更改文件的用户 ID
普通用户进程可以将文件的组 ID 修改为其所从属的任意附属组 ID ,前提条件是该进程的有效用户 ID 等于文件的用户 ID ;而超级用户进程可以将文件的组 ID 修改为任意值。
Linux 系统下,可以使用 getuid getgid 两个系统调用分别用于获取当前进程的用户 ID 和用户组 ID。

fchown lchown 函数

这两个同样也是系统调用,作用与 chown 函数相同,只是参数、细节方面有些许不同。fchown()、 lchown() 这两个函数与 chown() 的区别就像是 fstat() lstat() stat 的区别。

五、文件访问权权限

修改文件权限 chmod

Linux 系统下,可以使用 chmod 命令修改文件权限,该命令内部实现方法其实是调用了 chmod 函数, chmod 函数是一个系统调用,函数原型如下所示(可通过 "man 2 chmod" 命令查看):
#include <sys/stat.h>
int chmod(const char *pathname, mode_t mode);
首先,使用该函数需要包含头文件 <sys/stat.h>
函数参数及返回值如下所示:
pathname 需要进行权限修改的文件路径,若该参数所指为符号链接,实际改变权限的文件是符号链接所指向的文件,而不是符号链接文件本身。
mode 该参数用于描述文件权限,与 open 函数的第三个参数一样,这里不再重述,可以直接使用八进制数据来描述,也可以使用相应的权限宏(单个或通过位或运算符" | " 组合)。
返回值: 成功返回 0 ;失败返回 -1 ,并设置 errno
文件权限对于文件来说是非常重要的属性,是不能随随便便被任何用户所修改的,要想更改文件权限, 要么是超级用户(root )进程、要么进程有效用户 ID 与文件的用户 ID (文件所有者)相配。

六、文件的时间属性

3 个文件的时间属性:文件最后被访问的时间、文件内容最后被修改的时间以及文件状态最后被改变的时间,分别记录在 struct stat 结构体的 st_atim st_mtim 以及 st_ctim 变量中,如下所示:
                        
文件最后被访问的时间:访问指的是读取文件内容,文件内容最后一次被读取的时间,譬如使用read()函数读取文件内容便会改变该时间属性;
文件内容最后被修改的时间:文件内容发生改变,譬如使用 write() 函数写入数据到文件中便会改变该时间属性;
文件状态最后被改变的时间:状态更改指的是该文件的 inode 节点最后一次被修改的时间,譬如更 改文件的访问权限、更改文件的用户 ID 、用户组 ID 、更改链接数等,但它们并没有更改文件的实 际内容,也没有访问(读取)文件内容。为什么文件状态的更改指的是 inode 节点的更改呢? inode 中包含了很多文件信息,譬如:文件字节大 小、文件所有者、文件对应的读/ / 执行权限、文件时间戳(时间属性)、文件数据存储的 block (块)等,所以由此可知,状态的更改指的就是 inode 节点内容的更改。譬如 chmod() chown() 等 这些函数都能改变该时间属性。

七、符号链接(软链接)与硬链接

Linux 系统中有两种链接文件,分为软链接(也叫符号链接)文件和硬链接文件,软链接文件也就是前面给大家的 Linux 系统下的七种文件类型之一,其作用类似于 Windows 下的快捷方式。
那么硬链接文件又是什么呢?
首先,从使用角度来讲,两者没有任何区别,都与正常的文件访问方式一样,支持读、写以及执行。
Tips:使用 ln 命令可以为一个文件创建软链接文件或硬链接文件,用法如下:
硬链接:ln 源文件 链接文件
软链接:ln -s 源文件 链接文件
关于该命令其它用法,可以查看 man 手册。

硬链接:

使用 ln 命令创建的两个硬链接文件与源文件 test_file 都拥有相同的 inode 号,既然 inode 相同,也就意味着它们指向了物理硬盘的同一个区块,仅仅只是文件名字不同而已,创建出来的硬链接文件与源文件对文件系统来说是完全平等的关系。
如果删除了硬链接文件或源文
件其中之一,那文件所对应的 inode 以及文件内容在磁盘中的数据块会被文件系统回收吗?事实并不会这样,因为 inode 数据结结构中会记录文件的链接数,这个链接数指的就是硬链接数。
使用 ln 命令创建的两个硬链接文件与源文件 test_file 都拥有相同的 inode 号,既然 inode 相同,也就意味着它们指向了物理硬盘的同一个区块,仅仅只是文件名字不同而已,创建出来的硬链接文件与源文件对文件系统来说是完全平等的关系。同时源文件自身也是一个硬链接文件。

软链接:

软链接文件与源文件有着不同的 inode 号, 所以也就 是意味着它们之间有着不同的数据块,但是软链接文件的数据块中存储的是源文件的路径名,链接文件可以通过这个路径找到被链接的源文件,它们之间类似于一种“主从”关系,当源文件被删除之后,软链接文件依然存在,但此时它指向的是一个无效的文件路径,这种链接文件被称为悬空链接。

软硬链接的优劣

介绍完它们之间的区别之后,大家可能觉得硬链接相对于软链接来说有较大的优势,其实并不是这样, 对于硬链接来说,存在一些限制情况,如下:
不能对目录创建硬链接(超级用户可以创建,但必须在底层文件系统支持的情况下)。
硬链接通常要求链接文件和源文件位于同一文件系统中。
而软链接文件的使用并没有上述限制条件,优点如下所示:
可以对目录创建软链接;
可以跨越不同文件系统;
可以对不存在的文件创建软链接。

创建链接文件

Linux 系统下,可以使用系统调用创建硬链接文件或软链接文件
创建硬链接 link()
创建软链接 symlink()

读取软链接文件本身

软链接文件数据块中存储的是被链接文件的路径信息,那如何读取出软链接文件中 存储的路径信息呢?大家认为使用 read 函数可以吗?答案是不可以,因为使用 read 函数之前,需要先 open 打开该文件得到文件描述符,但是调用 open 打开一个链接文件本身是不会成功的,因为打开的并不是链接 文件本身、而是其指向的文件,所以不能使用 read 来读取,那怎么办呢?可以使用系统调用 readlink

八、目录

但是目录作为一种特殊文件,并不适合使用前面介绍的文件 I/O 方式进行读写等操作。在 Linux 系统下,会有一些专门的系统调用或 C 库函数用于对文件夹进行操作,譬如:打开、创建文件夹、删除文件夹、读取文件夹以及遍历文件夹中的文件等。

目录存储形式

所以对此总结如下:
普通文件由 inode 节点和数据块构成
目录由 inode 节点和目录块构成

创建和删除目录

使用 open 函数可以创建一个普通文件,但不能用于创建目录文件,在 Linux 系统下,提供了专门用于 创建目录 mkdir()以及删除目录 rmdir 相关的系统调用。

打开、读取以及关闭目录

打开、读取、关闭一个普通文件可以使用 open() read() close() ,而对于目录来说,可以使用 opendir() 、 readdir()和 closedir() 来打开、读取以及关闭目录。
  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值