Linux应用开发:文件属性与目录(上)

举报
JeckXu666 发表于 2022/01/15 00:14:56 2022/01/15
【摘要】 目录 Linux应用开发:文件属性与目录(上)一、文件类型1.1 普通文件1.2 目录文件1.3 字符设备文件和块设备文件1.4 符号链接文件1.5 管道文件1.6 套接字文件 二、stat...

Linux应用开发:文件属性与目录(上)

一、文件类型

Linux 系统下一共分为 7 种文件类型:普通文件、目录、字符设备文件、块设备文件、符号链接文件、管道文件以及套接字文件,这7个文件主要有以下区别:

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

下面详细介绍一下各个文件:

1.1 普通文件

Linux 系统下是最常见的,如文本文件、二进制文件、源代码文件都是普通文件,也就是 一般意义上的文件;普通文件中的 数据存在系统磁盘中,文件中的内容可以以 字节为单位 进行存储于访问

普通文件可以分为两大类:文本文件和二进制文件:

  • 文本文件:文件中的内容是由文本构成的,文本指的是 ASCII 码字符

  • 二进制文件:二进制文件中存储的本质上也是数字,只不过对于二进制文件来说,这些数字并不是文本字符编码,而是真正的 二进制数字

通过 stat 命令可以查询文件类型,如下:

20211219195338

ls 指令也可以查看文件类型:

20211219195544

用 ls 展开后,每个文件的第一个是一个 ‘-’,其含义如下:

  • ’ - ':普通文件
  • ’ d ':目录文件(dir)
  • ’ c ':字符设备文件(char)
  • ’ b ':块设备文件(block)
  • ’ l ':符号链接文件(link)
  • ’ s ':套接字文件(socket)
  • ’ p ':管道文件(pipeline)

1.2 目录文件

目录文件就是文件夹,是一种特殊文件,可以使用 vim 打开:

20211219200155

文件夹中记录了该文件夹本省的路径以及该文件夹下所存放的文件

1.3 字符设备文件和块设备文件

Linux 系统下,一切皆文件,也包括各种硬件设备,设备文件(字符设备文件、块设备文件)对应的是硬件设备,在 Linux 系统中,硬件设备会对应到一个设备文件,应用程序通过对设备文件的读写来操控、使用硬件设备

虽然有设备文件,但是设备文件并不对应磁盘上的一个文件,而是由文件系统虚拟出来的,一般是由内存来维护,当系统关机时,设备文件都会消失

字符设备文件一般存放在 Linux 系统/dev/目录下,所以/dev 也称为虚拟文件系统 devfs

列出 Ubuntu 下的文件, agpgart、autofs、btrfs-control、console 等这些都是字符设备文件,而 loop0、loop1 这些便是块设备文件,我们可以根据第一个字符来判断

20211219200504

1.4 符号链接文件

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

理解为 Windows 下的快捷方式

1.5 管道文件

管道文件是建立在内存之上可以同时被两个进程访问的文件,主要用于进程间通信

1.6 套接字文件

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

二、stat 函数

2.1 stat() 函数

使用 stat 命令查看文件的属性,本质上是通过调用 stat() 函数来获取文件属性,stat 函数是 Linux 中的系统调用,用于获取文件相关的信息,函数原型如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);

  
 
  • 1
  • 2
  • 3
  • 4

pathname用于指定一个需要查看的文件路径

buf:struct stat 类型指针,用于指向一个 struct stat 结构体变量。调用 stat 函数的时候需要传入一个 struct
stat 变量的指针,获取到的文件属性信息就记录在 struct stat 结构体中

返回值:成功返回 0;失败返回-1,并设置 error

2.2 struct stat 结构体

结构体原型:

struct stat
{
    dev_t st_dev;
    /* 文件所在设备的 ID */
    ino_t st_ino;
    /* 文件对应 inode 节点编号 */
    mode_t st_mode; /* 文件对应的模式 */
    nlink_t st_nlink;
    /* 文件的链接数 */
    uid_t st_uid;
    /* 文件所有者的用户 ID */
    gid_t st_gid;
    /* 文件所有者的组 ID */
    dev_t st_rdev;
    /* 设备号(指针对设备文件) */
    off_t st_size;
    /* 文件大小(以字节为单位) */
    blksize_t st_blksize;
    /* 文件内容存储的块大小 */
    blkcnt_t st_blocks;
    /* 文件内容所占块数 */
    struct timespec st_atim;
    /* 文件最后被访问的时间 */
    struct timespec st_mtim;
    /* 文件内容最后被修改的时间 */
    struct timespec st_ctim;
    /* 文件状态最后被改变的时间 */
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

st_mode 是 struct stat 结构体中的一个成员变量,是一个 32 位无符号整形数据,该变量记录了文件的类型、文件的权限这些信息,该整形各位如下:

20211219201357

  • O 对应的 3 个 bit 位用于描述其它用户的权限
  • G 对应的 3 个 bit 位用于描述同组用户的权限
  • U 对应的 3 个 bit 位用于描述文件所有者的权限
  • S 对应的 3 个 bit 位用于描述文件的特殊权限

文件类型这 4 个 bit 位用于描述该文件的类型:

S_IFSOCK 0140000 socket(套接字文件)
S_IFLNK 0120000 symbolic link(链接文件)
S_IFREG 0100000 regular file(普通文件)
S_IFBLK 0060000 block device(块设备文件)
S_IFDIR 0040000 directory(目录)
S_IFCHR 0020000 character device(字符设备文件)
S_IFIFO 0010000 FIFO(管道文件)

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

成员变量中的 struct timespec 结构体是 Linux 系统中时间相关的结构体,用于存储时间信息,原型如下:

struct timespec
{
    time_t tv_sec;
    /* 秒 */
    syscall_slong_t tv_nsec;
    /* 纳秒 */
};

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

三、fstat 和 lstat

除了 stat 函数之外,还可以使用 fstat 和 lstat 两个系统调用来获取文件属性信息,fstat、lstat 与 stat 的作用一样,但是参数、细节方面有些不同

3.1 fstat 函数

stat 是从文件名出发得到文件属性信息,不需要先打开文件;而 fstat 函数则是从文件描述符出发得到文件属性信息,函数原型

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int fstat(int fd, struct stat *buf);

  
 
  • 1
  • 2
  • 3
  • 4
  • 5

如果不想通过打开文件来得到文件属性信息,那么就使用 stat,如果文件已经打开了,那么就使用 fstat

3.2 lstat 函数

对于符号链接文件,stat、fstat 查阅的是符号链接文件所指向的文件对应的文件属性信息,而 lstat 查阅的是符号链接文件本身的属性信息,函数原型如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int lstat(const char *pathname, struct stat *buf);

  
 
  • 1
  • 2
  • 3
  • 4

四、文件归属

Linux 是一个多用户操作系统,系统中一般存在着好几个不同的用户,而 Linux 系统中的每一个文件都有一个与之相关联的用户和用户组,通过这个信息可以 判断文件的所有者和所属组

Linux 系统会为每一个用户或用户组分配一个 ID,将用户名或用户组名与对应的 ID 关联起来,所以 系统通过用户 ID(UID)或组 ID(GID)就可以识别出不同的用户和用户组

如下,我们查看一个文件的信息,可以看到他的 UID 和 GID:

20211219202516

文件的用户 ID 和组 ID 分别由 struct stat 结构体中的 st_uid 和 st_gid 所指定

而对于一个进程来说也有所属组,与一个进程相关联的 ID 一般有 5 个或更多,具体可以分为以下部分:

20211219203137

  • 实际用户 ID 和实际组 ID 就是 执行该进程的用户是谁、以及该用户对应的所属组;实际用户 ID 和实际组 ID 确定了进程所属的用户和组
  • 有效用户 ID、有效组 ID 以及附属组 ID 用于文件访问权限检查

"进程对文件是否拥有 xx 权限" 其实质是当前执行该进程的用户是否拥有对文件的 xx 权限

chown 是一个系统调用,该系统调用可用于改变文件的所有者(用户 ID)和所属组(组 ID),函数原型如下:

#include <unistd.h>
int chown(const char *pathname, uid_t owner, gid_t group);

  
 
  • 1
  • 2
  • pathname用于指定一个需要修改所有者和所属组的文件路径
  • owner:将 文件的所有者 修改为该参数指定的用户(以用户 ID 的形式描述)
  • group:将 文件的所属组 修改为该参数指定的用户组(以用户组 ID 的形式描述)
  • 返回值:成功返回 0;失败将返回-1,兵并且会设置 errno

函数使用注意:

  • 只有超级用户进程能更改文件的用户 ID
  • 普通用户进程只能将文件的组 ID 修改为其所从属的任意附属组 ID,前提条件是该进程的有效用户 ID 等于文件的用户 ID;而 超级用户进程可以将文件的组 ID 修改为任意值

文章来源: blog.csdn.net,作者:JeckXu666,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/qq_45396672/article/details/122029580

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。