操作系统:文件属性

本文详细介绍了Linux中文件的7种类型(普通文件、目录、字符设备、块设备、FIFO、套接字和符号链接),展示了如何查看文件属性,区分字符设备与块设备,以及空洞文件的创建和意义。重点讲解了文件权限掩码的修改和文件权限的理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文件类型

在Linux下一切皆是文件,从应用层(应用程序层)看待底层机制时,皆以文件的方式来看待这些机制.但是不同的底层机制,毕竟是不同的,比如底层驱动程序,就分为字符设备驱动和块设备驱动,根据底层机制的不同,文件被分为了7种类型,分布是 - d c s p c b

普通文件(regular file:-)

普通文件根据存放的内容的不同,又分为如下两种

  • 文本文件
    存放的都是文字编码,文本编辑器打开后,会将这些文字编码翻译为文字图形,以供人识别。
  • 纯二进制文件(机器码)
    比如经过编译后得到的可执行文件,里面放的是cpu执行的纯二进制机器码,由于文编编辑器只认识文字编码,所以用文本编辑器打开后,显示的内容无法是错乱的,无法辨识。

其实不管存放的是文字编码,还是机器码,在计算机中存储时,其实都是以二进制形式存放的,只不过我们这里可刻意的把机器码这类非文字编码的数据,特意强调为了二进制数据。

目录文件(directory file:d)

目录是一种特殊的文件,专门用于管理其他文件。

字符特殊文件( character special file: c)

字符设备文件,就是字符设备驱动程序,在上层的表现形式。

当应用程序调用底层字符设备驱动程序,实现对某个字符设备进行读写时,上层就需要对接底层的字符驱动程序,字符设备驱动在上层,会以"字符设备文件"的形式表现出来,我们通过open、read、write去读写字符设备文件,就实现了和底层字符设备驱动程序的交互。

块设备文件(block special file: b):对应块设备(如磁盘等)。

块设备文件,是块设备驱动程序在上层的表现形式。

字符设备与块设备有什么区别?

  • 字符设备
    以字节为单位来操作数据。
    比如:键盘、鼠标、显示器都等是字符设备。
    字符设备的驱动程序,就称为"字符设备驱动程序”。
  • 块设备
    块设备存储的数据量往往非常答,为了提高读写效率,都是以块(1024字节)为单位来操作数据。
    比如:电脑硬盘、移动硬盘、u盘等,凡是涉及大量数据存储的,都是以块为单位来操作数据的,都是块设备。块设备的驱动程序,就成为"块设备驱动程序”。

FIFO(fifo:p)

管道文件,用于实现不同进程(程序)之间的通信,管道是os提供的一种纯代码层面的通信机制。
A 进程 ⟶ 数据 管道文件 ⟶ 数据 B 进程 A进程\overset{数据}{\longrightarrow}管道文件\overset{数据}{\longrightarrow}B进程 A进程数据管道文件数据B进程

套接字文件( socket: s)

专门用于网络通信的文件。
讲到网络编程时,再来具体介绍。

符号连接(symbolic link: l):

其实就是一种快捷图标,背后指向了另外一个文件。

file 文件

查看文件属性

  • 如果查看的是文本文件
    会提醒你,它是文字编码格式的文件。
  • 如果你查看的是纯二进制文件((机器码)
    会提示你,这是一个可以运行的可执行文件。
    a.out: ELF 64-bit LSB executable, x86-64,dynamically linked,/lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32,not strippe
    • ELF: Linux下可执行文件的格式,windows下的可执行文件是PE格式对
      应格式的可执行文件,只能在对应的os下运行。
    • 64-bit:文件里面的机器码是64位.的
    • LSB:小端序
    • executable:明确告诉你,该文件是一个可执行文件·x86-64:运行的是x86架构64位的cpu
    • dynamically linked,/ lib64/ ld-linux-x86-64.so.2
      程序使用的库是动态链接库,库名叫/lib64/ld-linux-x86-64.so.2
    • for GxU/Linux 2.6.32:运行的系统是Linux系统〈ubuntu) , Linux 2.6.32是ubuntu所用Linux内核的版本号
    • not strippe:程序没有被瘦身,里面包含有各种用于调试用的信息,当这个程序最终发布时,会使用strip命令为程序瘦身,去除里面的无用信息,让程序变的更小。

获取文件属性

stat、lstat、fstat函数

ls命令其实就是调用了这三个函数中的lstat来实现的,我们可以调用lstat函数来自己实现一个ls命令。

stat函数

#include <sys/types.h>                                                               
#include <sys/stat.h>                                                               
#include <unistd.h>    
int stat(const char *path, struct stat *statbuf); 
int lstat(const char *path, struct stat *statbuf);
int fstat(int fd, struct stat *statbuf);

statlstat唯一的区别就是stat获取链接文件属性时会直接获取链接指向的文件的属性,而lstat会返回链接文件的属性,而fstatstat唯一区别是fstat使用文件描述符而非文件路径。

  1. 功能:获取文件的属性信息。
    每个文件的属性信息,都是存在块设备上,该文件自己的inode节点(索引节点)空间中。
    调用stat函数时,文件系统通过stat给的path,到块设备上索引到该文件的inode节点空间,然后将里面的文件属性信息,读到应用程序的缓存中,如此就得到了文件的属性信息。

    文件属性数据中转的过程:
    应用缓存<–stat函数提供的内核缓存<–驱动程序的缓存<–块设备上的inode结点

  2. 返回值
    调用成功,返回0,失败返回-1,errno被设置。

  3. 参数

    • path:文件路径名
    • statbuf:应用缓存,用于存放读到的文件属性信息
struct stat{
	dev_t st_dev;/*块设备号(ID)*/
	ino_t st_ino;/*inode结点号,文件属性信息所存inode节点的编号*/
	mode_t l st_mode;/*文件类型和文件权限 ls*/
	nlink_t st_nlink;/*链接数 ls*/
	uid_t st_uid;/*文件所属用户ID ls*/
	gid_t st_gid;/*文件所属组ID ls*/
	dev_t st_rdev;/*字符设备ID*/
	off_t st_size;/*文件大小*/
	blksize_t st_blksize;/*系统每次按块IO操作时,块的大小(一般是512或1024)*/
    blkcnt_t st_blocks;/*块的索引号*/
/*windows下,文件的时间,同样也分为这三种*/
    time_t st_atime;/*最后一次访问时间,read ls*/
    time_t st_mtime;/*最后一次修改时间,write*/
	time_t st_ctime;/*最后一次属性修改的时间,如权限被修改,文件所有者(属主)被修改*/
};
//其中有ls标记的是ls会显示的内容

st_mode

st_mode 本质就是一个16位二进制数
文件类型 设置位 文件权限
**** **** *** *** ***

  • 文件类型(定义在<sys/stat.h>)

    二进制含义
    (1000 000000000000)代表普通文件
    (0100 000000000000)代表目录文件
    (0110 000000000000)代表块设备文件
    (0011 000000000000)代表字符设备文件
    (0001 000000000000)代表管道文件
    (1100 000000000000)代表套接字文件
    (1010 000000000000)代表符号链接文件
  • 文件权限
    user group other
    r w x r w x r w x
    0 1 - 0 1 - 0 1 -

st_size

文件长度,只对普通文件、目录及符号链接有意义因为只有普通文件、目录、以及符号链接文件才有实际的数据,有数据才有文件长度。其它的文件在块设备上只存储了文件属性,它们只是挂了一个文件名,以文件的形式进行管理而已,没有实际的数据,所以对于这些文件来说,文件大小是没有意义的。

符号链接文件就是一个快捷键,背后指向了某个文件。
符号链接文件的数据,就是所指向文件的文件名,所以它的文件大小指的就是这个文件名的字符个数。

#include <unistd.h>
#include <sys/types.h>
int truncate(const char *path,off_t length);
int ftruncate(int fd, off_t length) ;

函数功能:将文件长度截短为length所指定长度。
truncate利用文件路径名操作,ftruncate利用文件描述符操作。

length的大小可以大于文件实际大小,文件截断长度>文件长度时,多余的部分填放空洞。

ls查看到的只是文件的理论大小,但是空洞部分并不占用实际物理存储空间。du命令:查看文件在块设备上,实际占用的物理空间。

在一般文件的情况下,对于普通文件来说,文件数据的理论大小=在块设备上实际占用的空间大小。
但是空洞文件却不是这样的,对于空洞文件来说,文件数据的理论大小〉在块设备上实际占用的空间大小。

空洞文件的意义

打个比方,我承诺给你一亩地,但是你又不是马上就要用满这一亩地,是一点一点来占用的,如果我现在一下子就把一亩地全部给你,但是你要花费很久时间才会把地全用上,在你占满之前,一直有相当部分的空间被闲置不用,显然非常浪费空间资源。
解决办法是,我先承诺说给你一亩地,但是这一亩地先不全部给你,你搬一部分东西过来时,我给你一部分空间,按照这样的方式,直到把1亩地的空间全部给你,在你没有用满一亩地之前,其它的空间我就可以用作它用。

制作空洞文件
  • truncate、ftrucate制作
    文件截短长度>文件长度时,多余的部分就是空洞。
  • 使用lseek制作
    将文件读写位置调整到文件尾部之后,然后写点数据,中间空出的部分就是空洞。

文件权限掩码

111 111 111 (0777) 指定权限
&
~000 000 010 (0002)文件权限掩码

111 111 101 (0775) 实际文件权限

文件权限掩码是用来限制其他用户的权限,防止其他用户修改你的文件

每一个进程都有一个文件权限掩码,进程修改只是当前进程的文件权限掩码,对其它进程的文件权限掩码无影响。

如何修改文件权限掩码

#include <sys/types.h>                                                               
#include <sys/stat.h>                                                               
mode_t umask(mode_t mask); 
  1. 功能:修改文件权限掩码
  2. 参数
    mask:新的文件权限掩码
  3. 返回值
    umask不会调用失败。返回值是旧的文件权限掩码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Shilong Wang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值