【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构

简介: 【Linux系统编程】Linux 文件系统探究:深入理解 struct dirent、DIR 和 struct stat结构

struct dirent 和 DIR 结构体的深入解析

1. 引言

Linux系统编程中,目录操作是一个不可或缺的环节。为了实现这一目的,C语言提供了一系列的API,其中struct direntDIR结构体是最常用的。这篇文章将深入探讨这两个结构体的内部机制,设计哲学,以及如何在实际编程中使用它们。

“C makes it easy to shoot yourself in the foot; C++ makes it harder, but when you do it blows your whole leg off.” — Bjarne Stroustrup, 《The C++ Programming Language》

2. struct dirent 结构体

2.1 定义和组成

struct dirent结构体用于表示一个目录项。其定义如下:

struct dirent
{
   long d_ino; /* inode number 索引节点号 */
   off_t d_off; /* offset to this dirent 在目录文件中的偏移 */
   unsigned short d_reclen; /* length of this d_name 文件名长 */
   unsigned char d_type; /* the type of d_name 文件类型 */
   char d_name [NAME_MAX+1]; /* file name (null-terminated) 文件名,最长255字符 */
}
  • d_ino: Inode number(Inode编号)
  • d_off: Offset(偏移量)
  • d_reclen: Length of this record(该记录的长度)
  • d_type: Type of file(文件类型)
  • d_name: Null-terminated filename(以null结尾的文件名)

2.2 使用场景

当我们使用readdir()函数读取目录信息时,该函数会返回一个指向struct dirent结构体的指针。

#include <dirent.h>
struct dirent *readdir(DIR *dirp);

3. DIR 结构体

3.1 定义和组成

DIR结构体是一个目录流(Directory Stream)的类型定义,它在头文件中被声明为一个不透明的数据类型。

typedef struct __dirstream DIR;
struct __dirstream
{
void *__fd; /* `struct hurd_fd' pointer for descriptor.   */
char *__data; /* Directory block.   */
int __entry_data; /* Entry number `__data' corresponds to.   */
char *__ptr; /* Current pointer into the block.   */
int __entry_ptr; /* Entry number `__ptr' corresponds to.   */
size_t __allocation; /* Space allocated for the block.   */
size_t __size; /* Total valid data in the block.   */
__libc_lock_define (, __lock) /* Mutex lock for this structure.   */
};
typedef struct __dirstream DIR;

3.2 使用场景

DIR结构体通常与opendir(), readdir(), closedir()等函数一起使用,以实现目录的打开、读取和关闭。

DIR *opendir(const char *name);
int closedir(DIR *dirp);

4. 示例代码

下面是一个简单的代码示例,展示了如何使用struct direntDIR结构体。

#include <stdio.h>
#include <dirent.h>
int main() {
    DIR *dir;
    struct dirent *ent;
    dir = opendir("/tmp");
    if (dir != NULL) {
        while ((ent = readdir(dir)) != NULL) {
            printf("%s\n", ent->d_name);
        }
        closedir(dir);
    } else {
        perror("Couldn't open directory");
    }
    return 0;
}

5. struct stat 结构体与文件类型枚举

5.1 struct stat 结构体

struct stat结构体用于存储文件或文件系统的信息。其定义如下:

struct stat {
    mode_t st_mode;
    ino_t st_ino;
    dev_t st_dev;
    dev_t st_rdev;
    nlink_t st_nlink;
    uid_t st_uid;
    gid_t st_gid;
    off_t st_size;
    time_t st_atime;
    time_t st_mtime;
    time_t st_ctime;
    blksize_t st_blksize;
    blkcnt_t st_blocks;
};

这个结构体包含了丰富的文件属性信息,例如文件模式(st_mode)、i-node节点号(st_ino)、文件大小(st_size)等。

5.2 文件类型枚举

在Linux系统中,文件类型是通过一个枚举(enum)来定义的,具体如下:

enum {
    DT_UNKNOWN = 0,
    DT_FIFO = 1,
    DT_CHR = 2,
    DT_DIR = 4,
    DT_BLK = 6,
    DT_REG = 8,
    DT_LNK = 10,
    DT_SOCK = 12,
    DT_WHT = 14
};

这些枚举值通常用于struct dirent结构体中的d_type字段,以标识文件的类型。

5.3 结合应用

当我们使用stat()fstat()函数获取文件信息时,这些函数会返回一个填充了struct stat结构体的指针。同时,我们可以通过struct direntd_type字段,用上面的枚举值来判断文件类型。

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct stat sb;
if (stat("/path/to/file", &sb) == 0) {
    mode_t mode = sb.st_mode;
    // 判断文件类型和权限等
}

6. 深度见解

在探讨struct direntDIR结构体时,我们不仅看到了数据结构的设计,还能观察到一种对文件系统的抽象和简化。这种设计哲学反映了一种追求效率和简洁的思维方式。

“Simplicity is prerequisite for reliability.” — Edsger W. Dijkstra

在探究struct stat和文件类型枚举时,我们看到了操作系统如何通过数据结构和枚举来抽象和管理文件系统。这不仅体现了编程的实用性,也反映了对底层复杂性的高度抽象。

“The art of programming is the skill of controlling complexity.” — Marijn Haverbeke

这种设计哲学不仅使得文件操作更为高效,也让我们更容易理解和使用这些复杂的系统功能。

7. 结论

struct direntDIR结构体是Linux系统编程中非常重要的组成部分。通过这两个结构体,我们不仅可以高效地操作文件系统,还能更深入地理解Linux系统的设计哲学。

希望这篇文章能帮助你更全面地理解这两个结构体的用途和内部机制。

结语

在我们的编程学习之旅中,理解是我们迈向更高层次的重要一步。然而,掌握新技能、新理念,始终需要时间和坚持。从心理学的角度看,学习往往伴随着不断的试错和调整,这就像是我们的大脑在逐渐优化其解决问题的“算法”。

这就是为什么当我们遇到错误,我们应该将其视为学习和进步的机会,而不仅仅是困扰。通过理解和解决这些问题,我们不仅可以修复当前的代码,更可以提升我们的编程能力,防止在未来的项目中犯相同的错误。

我鼓励大家积极参与进来,不断提升自己的编程技术。无论你是初学者还是有经验的开发者,我希望我的博客能对你的学习之路有所帮助。如果你觉得这篇文章有用,不妨点击收藏,或者留下你的评论分享你的见解和经验,也欢迎你对我博客的内容提出建议和问题。每一次的点赞、评论、分享和关注都是对我的最大支持,也是对我持续分享和创作的动力。

目录
相关文章
|
6月前
|
Ubuntu Linux Anolis
Linux系统禁用swap
本文介绍了在新版本Linux系统(如Ubuntu 20.04+、CentOS Stream、openEuler等)中禁用swap的两种方法。传统通过注释/etc/fstab中swap行的方式已失效,现需使用systemd管理swap.target服务或在/etc/fstab中添加noauto参数实现禁用。方法1通过屏蔽swap.target适用于新版系统,方法2通过修改fstab挂载选项更通用,兼容所有系统。
591 3
Linux系统禁用swap
|
6月前
|
Linux
Linux系统修改网卡名为eth0、eth1
在Linux系统中,可通过修改GRUB配置和创建Udev规则或使用systemd链接文件,将网卡名改为`eth0`、`eth1`等传统命名方式,适用于多种发行版并支持多网卡配置。
1125 3
|
Ubuntu Linux 网络安全
Linux系统初始化脚本
一款支持Rocky、CentOS、Ubuntu、Debian、openEuler等主流Linux发行版的系统初始化Shell脚本,涵盖网络配置、主机名设置、镜像源更换、安全加固等多项功能,适配单/双网卡环境,支持UEFI引导,提供多版本下载与持续更新。
698 3
Linux系统初始化脚本
|
6月前
|
安全 Linux Shell
Linux系统提权方式全面总结:从基础到高级攻防技术
本文全面总结Linux系统提权技术,涵盖权限体系、配置错误、漏洞利用、密码攻击等方法,帮助安全研究人员掌握攻防技术,提升系统防护能力。
778 1
|
6月前
|
监控 安全 Linux
Linux系统提权之计划任务(Cron Jobs)提权
在Linux系统中,计划任务(Cron Jobs)常用于定时执行脚本或命令。若配置不当,攻击者可利用其提权至root权限。常见漏洞包括可写的Cron脚本、目录、通配符注入及PATH变量劫持。攻击者通过修改脚本、创建恶意任务或注入命令实现提权。系统管理员应遵循最小权限原则、使用绝对路径、避免通配符、设置安全PATH并定期审计,以防范此类攻击。
1224 1
|
6月前
|
Linux 应用服务中间件 Shell
二、Linux文本处理与文件操作核心命令
熟悉了Linux的基本“行走”后,就该拿起真正的“工具”干活了。用grep这个“放大镜”在文件里搜索内容,用find这个“探测器”在系统中寻找文件,再用tar把东西打包带走。最关键的是要学会使用管道符|,它像一条流水线,能把这些命令串联起来,让简单工具组合出强大的功能,比如 ps -ef | grep 'nginx' 就能快速找出nginx进程。
770 1
二、Linux文本处理与文件操作核心命令
|
6月前
|
Linux
linux命令—stat
`stat` 是 Linux 系统中用于查看文件或文件系统详细状态信息的命令。相比 `ls -l`,它提供更全面的信息,包括文件大小、权限、所有者、时间戳(最后访问、修改、状态变更时间)、inode 号、设备信息等。其常用选项包括 `-f` 查看文件系统状态、`-t` 以简洁格式输出、`-L` 跟踪符号链接,以及 `-c` 或 `--format` 自定义输出格式。通过这些选项,用户可以灵活获取所需信息,适用于系统调试、权限检查、磁盘管理等场景。
452 137
|
6月前
|
安全 Ubuntu Unix
一、初识 Linux 与基本命令
玩转Linux命令行,就像探索一座新城市。首先要熟悉它的“地图”,也就是/根目录下/etc(放配置)、/home(住家)这些核心区域。然后掌握几个“生存口令”:用ls看周围,cd去别处,mkdir建新房,cp/mv搬东西,再用cat或tail看文件内容。最后,别忘了随时按Tab键,它能帮你自动补全命令和路径,是提高效率的第一神器。
1204 58
|
5月前
|
存储 安全 Linux
Linux卡在emergency mode怎么办?xfs_repair 命令轻松解决
Linux虚拟机遇紧急模式?别慌!多因磁盘挂载失败。本文教你通过日志定位问题,用`xfs_repair`等工具修复文件系统,三步快速恢复。掌握查日志、修磁盘、验重启,轻松应对紧急模式,保障系统稳定运行。
1060 2
|
6月前
|
缓存 监控 Linux
Linux内存问题排查命令详解
Linux服务器卡顿?可能是内存问题。掌握free、vmstat、sar三大命令,快速排查内存使用情况。free查看实时内存,vmstat诊断系统整体性能瓶颈,sar实现长期监控,三者结合,高效定位并解决内存问题。
599 0
Linux内存问题排查命令详解