ext2文件体系

ext2文件体系

image-20250723204052354

对文件进行操作

文件的磁盘存放

stat(用法)

1
int stat(const char *path, struct stat *buf);
  • 参数含义char *path 传入文件的路径
  • struct stat *buf 指向一个 struct stat 类型的指针,该结构用于存储文件的状态信息
  • 调用成功后,buf 会填充相关数据。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>  
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(int argc,char *argv[]){
struct stat s_buf;
if(argc<2){
printf("./mycp src dest\n");
exit(1);
}
/*成功返回0*/
if(stat(argv[1],&s_buf)<0){
perror("stat");
exit(1);
}
printf("%s\t%d\n",argv[1],s_buf.st_size);
return 0;
}

stat结构体

stat结构体内容是一个结构体里面存放的内容有
![[Pasted image 20250722160204.png]]

结构体包含的内容

字段名 类型 描述
st_dev dev_t 文件所在的设备 ID
st_ino ino_t 文件的 i 节点号(Inode Number),唯一标识文件
st_mode mode_t 文件类型和权限位(如读、写、执行权限)
st_nlink nlink_t 文件的硬链接数
st_uid uid_t 文件所有者用户 ID
st_gid gid_t 文件所属组 ID
st_size off_t 文件大小(以字节为单位),常规文件有效
st_atime time_t 文件最后访问时间(Atime)
st_mtime time_t 文件最后修改时间(Mtime)
st_ctime time_t 文件状态最后更改时间(Ctime)
st_blksize blksize_t 文件系统 I/O 优化的块大小(字节)
st_blocks blkcnt_t 文件占用的块数(通常 512 字节为单位)
st_mode中的所以权限位操作

在 POSIX 系统中,st_mode 字段(类型为 mode_t)存储了文件的类型和权限信息。它是一个位字段,通常通过位操作(例如 &)提取具体权限。

文件类型位

这些位定义了文件的类型(仅有一个位会置位):

  • S_IFREG (0100000): 常规文件
  • S_IFDIR (0040000): 目录
  • S_IFLNK (0120000): 符号链接
  • S_IFBLK (0060000): 块设备文件
  • S_IFCHR (0020000): 字符设备文件
  • S_IFIFO (0010000): 命名管道 (FIFO)
  • S_IFSOCK (0140000): 套接字
权限位

权限分为三类(文件所有者、组、其他用户),每类包含读(R)、写(W)、执行(X)权限:

  • 文件所有者权限:
    • S_IRUSR (0400): 读权限
    • S_IWUSR (0200): 写权限
    • S_IXUSR (0100): 执行/搜索权限
  • 组权限:
    • S_IRGRP (0040): 读权限
    • S_IWGRP (0020): 写权限
    • S_IXGRP (0010): 执行/搜索权限
  • 其他用户权限:
    • S_IROTH (0004): 读权限
    • S_IWOTH (0002): 写权限
    • S_IXOTH (0001): 执行/搜索权限
特殊权限位
  • S_ISUID (04000): 设置用户 ID(Set User ID),执行文件时以文件所有者身份运行。
  • S_ISGID (02000): 设置组 ID(Set Group ID),执行文件时以文件所属组身份运行,或对目录启用强制组。
  • S_ISVTX (01000): 粘滞位(Sticky Bit),限制删除权限(常用于公共目录)。
示例
  • 八进制 0644 表示权限 rw-r--r--
    • 所有者:读写 (0400 | 0200 = 0600)
    • 组:只读 (0040)
    • 其他:只读 (0004)
  • 八进制 4755 表示权限 rwsr-xr-x
    • 包含 S_ISUID (04000),所有者执行时以文件所有者身份运行。
注意
  • 这些值是八进制表示,实际使用时通过位操作与 st_mode 进行比较(如 st_mode & S_IRUSR)。
  • 头文件 <sys/stat.h> 提供了这些宏定义。

希望这个列表对你有帮助!如果需要进一步解释或示例,可以告诉我。

1
stat hello
  • 创建时间
  • 更改时间(更改内容
  • 变更时间(更改inmod
  • 访问时间

stat的函数

1
stat(argv[1],&s_buf) < 0 

表示无法打开文件有问题(返回正确返回0)

小作业

自我实现一个 ls -l的小命令代码

access

实际用户ID
有效用户ID

chmod

1
int chmod(const char *path, mode_t mode);
  • path 文件的路径
  • mode 指定新的文件权限模式

chowm

1
int chown(const char *path, uid_t owner, gid_t group);
  • *const char path:
    • 表示目标文件的路径名,可以是相对路径或绝对路径。
    • 例如:”/home/user/file.txt” 或 “file.txt”。
    • 这个参数指向一个以 null 结尾的字符串,指定要更改所有者或组的文件名称。
  • uid_t owner:
    • 指定文件的新所有者用户 ID(User ID)。
    • uid_t 是一个整数类型,通常定义在 <sys/types.h> 中。
    • 如果设为 -1,表示不更改所有者,保留原有值。
    • 例如,0 表示 root 用户,具体用户 ID 需要通过 /etc/passwd 或 getpwnam 获取。
  • gid_t group:
    • 指定文件的新所属组 ID(Group ID)。
    • gid_t 也是一个整数类型,定义在 <sys/types.h> 中。
    • 如果设为 -1,表示不更改组,保留原有值。
    • 具体组 ID 可通过 /etc/group 或 getgrnam 获取。
  • 返回值:
    • 成功返回 0,失败返回 -1,并设置 errno 表示错误原因(如权限不足 EPERM 或文件不存在 ENOENT)。

      ![[Pasted image 20250723165054.png]]

int unlink(const char *pathname)

  1. 如果是符号链接,删除符号链接
  2. 如果是硬链接,硬链接数减1,当减为0时,释放数据块和inode
  3. 如果文件硬链接数为0,但有进程已打开该文件,并持有文件描述符,则等该进程关闭该文件时,kernel才真正 去删除该文件
  4. 利用该特性创建临时文件,先open或creat创建一个文件,马上unlink此文件

对目录进行操作

mkdir(创建一个目录)

1
int mkdir(const char *pathname ,mode_t mode);

rmdir(删除一个目录)

1
int rmdir(const char *pathname);

opendir(打开一个目录)

1
2
DIR *opendir()

得到一个目录项目指针

readdir(读目录中的内容

readdir 是一个 POSIX 函数,用于读取目录流中的目录条目。它从一个打开的目录(通过 opendir 返回的 DIR *)中依次返回目录中的文件和子目录信息。以下是其详细说明:

函数原型

1
struct dirent *readdir(DIR *dirp);
  • 参数:
    • DIR *dirp: 指向由 opendir 打开的目录流的指针。
  • 返回值:
    • 成功时返回一个指向 struct dirent 的指针,包含当前目录条目的信息。
    • 到达目录末尾或发生错误时返回 NULL
  • 头文件: <dirent.h>

工作原理

  • readdir 按未指定顺序(通常是文件系统内部存储顺序)返回目录中的每个条目。
  • 它会跳过 "."(当前目录)和 ".."(父目录)的处理取决于调用者的逻辑。
  • 每次调用会返回下一个条目,内部维护一个位置指针,直到所有条目读取完毕。
  • 该函数是线程安全的,但需要注意并发访问时可能需要加锁。

注意事项

  • 目录流 dirp 必须由 opendir 打开,调用 closedir 关闭后 readdir 不再有效。
  • 返回的 struct dirent 指针由 readdir 内部管理,调用者不应修改或释放其内存。
  • 如果目录内容在读取过程中发生变化(例如文件被删除或添加),行为未定义。

struct dirent 结构

struct dirent 定义了目录条目的结构,具体字段因系统实现而异,但 POSIX 标准定义了以下常见字段(在 <dirent.h> 中):

字段说明

字段名 类型 描述
d_ino ino_t 文件的 i 节点号(Inode Number),唯一标识文件
d_off off_t 目录流中下一条目的偏移量(某些系统可用)
d_reclen unsigned short 结构体的长度(字节数),便于跳过条目
d_type unsigned char 文件类型(可选,视系统支持),如 DT_REG (常规文件)、DT_DIR (目录)
d_name char[] 文件名,null 结尾的字符串,长度通常有限制(如 NAME_MAX

示例字段值

  • d_type(如果支持)可能的值:
    • DT_UNKNOWN (0): 未知类型
    • DT_REG (8): 常规文件
    • DT_DIR (4): 目录
    • DT_LNK (10): 符号链接
    • DT_FIFO (1): 命名管道
    • DT_SOCK (12): 套接字
    • DT_CHR (2): 字符设备
    • DT_BLK (6): 块设备

注意

  • d_name 是文件名,不包含路径,长度通常受限于 NAME_MAX(例如 255 字节)。

image-20250723203959107

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <dirent.h>
#include <stdio.h>

int main() {
DIR *dir = opendir(".");
if (dir == NULL) {
perror("opendir");
return 1;
}
struct dirent *entry;
while ((entry = readdir(dir)) != NULL) {
printf("Name: %s, Inode: %lu\n", entry->d_name, (unsigned long)entry->d_ino);
}
closedir(dir);
return 0;
}
  • 该代码读取当前目录的条目,打印文件名和 i 节点号。

希望这个解释清楚!如果需要更多细节或示例,请告诉我。

rewindir

1
void rewindir(DIR *dirp);

把目录指针返回到目录的起始位置

telldir/seekdir

closedir