linux文件系统基础--一个数据块能存储多少个目录项或者一个目录下能创建多少个文件

本文围绕Linux系统展开,介绍新建目录会占用一个block大小空间,一般EXT3的block为4KB。阐述目录是特殊文件,存储目录项,分析目录项结构体,计算可存储文件记录个数,还通过脚本验证计算结果,最后提出目录项大小计算的未解之谜。

新建目录也有大小

我们知道,在linux中一个新建的目录也会占用一个block大小的空间。一般EXT3的block大小为4KB。我们新建一个目录,验证一下:
2015-12-15 23-08-19屏幕截图.png-28.9kB

在linux中,目录其实也是一种文件,只不过相对于普通文件,它比较特殊,它存储的是一些目录项(dirent),每个目录项,由两部分组成:所包含文件的文件名,以及该文件名对应的inode号码。。可以参考<Linux文件存储结构,包括目录项、inode、数据块>和<linux下普通文件和目录文件区别 >,获得感性认识。

目录项结构体

引用The Second Extended File System的一张图来说明目录项的结构体。
2015-12-16 00-47-29屏幕截图.png-14.4kB
按照上面这张图,结构体前四项之和为8,又因为name至少有一个字符,而目录项又要求4字节对齐,所以一个目录项最小为12。可以存储文件记录的个数为4096/12 = 431...4。去掉新建目录时候默认建立的...目录,可以新建的文件个数为339个。

检验计算

我写了一个脚本验证:

  1. #! /bin/bash
  2.  
  3. if [ -d $1 ]; then
  4. cd $1
  5. fi
  6.  
  7. chrs="0 1 2 3 4 5 6 7 8 9 a b c d e f g h i j k l m n o p q r s t u v w x y z"
  8. count=0
  9.  
  10. for x in $chrs
  11. do
  12. for y in $chrs
  13. do
  14. let count=count+1
  15. if [ $count -gt $2 ]; then
  16. exit
  17. fi
  18. touch $x$y
  19. done
  20. done

新建一个空目录,如下操作

  1. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ mkdir test
  2. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls
  3. dirent.c dirent.o test touchfile.sh
  4. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ./touchfile.sh test/ 339
  5. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls -l
  6. 总用量 20
  7. -rw-rw-r-- 1 yiltoncent yiltoncent 166 12月 16 00:20 dirent.c
  8. -rwxrwxr-x 1 yiltoncent yiltoncent 7340 12月 16 00:20 dirent.o
  9. drwxrwxr-x 2 yiltoncent yiltoncent 4096 12月 16 00:54 test
  10. -rwxrwxr-x 1 yiltoncent yiltoncent 257 12月 16 00:54 touchfile.sh
  11. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls -s
  12. 总用量 20
  13. 4 dirent.c 8 dirent.o 4 test 4 touchfile.sh
  14. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls test/
  15. 00 09 0i 0r 10 19 1i 1r 20 29 2i 2r 30 39 3i 3r 40 49 4i 4r 50 59 5i 5r 60 69 6i 6r 70 79 7i 7r 80 89 8i 8r 90 99
  16. 01 0a 0j 0s 11 1a 1j 1s 21 2a 2j 2s 31 3a 3j 3s 41 4a 4j 4s 51 5a 5j 5s 61 6a 6j 6s 71 7a 7j 7s 81 8a 8j 8s 91 9a
  17. 02 0b 0k 0t 12 1b 1k 1t 22 2b 2k 2t 32 3b 3k 3t 42 4b 4k 4t 52 5b 5k 5t 62 6b 6k 6t 72 7b 7k 7t 82 8b 8k 8t 92 9b
  18. 03 0c 0l 0u 13 1c 1l 1u 23 2c 2l 2u 33 3c 3l 3u 43 4c 4l 4u 53 5c 5l 5u 63 6c 6l 6u 73 7c 7l 7u 83 8c 8l 8u 93 9c
  19. 04 0d 0m 0v 14 1d 1m 1v 24 2d 2m 2v 34 3d 3m 3v 44 4d 4m 4v 54 5d 5m 5v 64 6d 6m 6v 74 7d 7m 7v 84 8d 8m 8v 94 9d
  20. 05 0e 0n 0w 15 1e 1n 1w 25 2e 2n 2w 35 3e 3n 3w 45 4e 4n 4w 55 5e 5n 5w 65 6e 6n 6w 75 7e 7n 7w 85 8e 8n 8w 95 9e
  21. 06 0f 0o 0x 16 1f 1o 1x 26 2f 2o 2x 36 3f 3o 3x 46 4f 4o 4x 56 5f 5o 5x 66 6f 6o 6x 76 7f 7o 7x 86 8f 8o 8x 96
  22. 07 0g 0p 0y 17 1g 1p 1y 27 2g 2p 2y 37 3g 3p 3y 47 4g 4p 4y 57 5g 5p 5y 67 6g 6p 6y 77 7g 7p 7y 87 8g 8p 8y 97
  23. 08 0h 0q 0z 18 1h 1q 1z 28 2h 2q 2z 38 3h 3q 3z 48 4h 4q 4z 58 5h 5q 5z 68 6h 6q 6z 78 7h 7q 7z 88 8h 8q 8z 98
  24. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ rm -r test/
  25. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ mkdir test
  26. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ./touchfile.sh test/ 340
  27. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls -l
  28. 总用量 28
  29. -rw-rw-r-- 1 yiltoncent yiltoncent 166 12月 16 00:20 dirent.c
  30. -rwxrwxr-x 1 yiltoncent yiltoncent 7340 12月 16 00:20 dirent.o
  31. drwxrwxr-x 2 yiltoncent yiltoncent 12288 12月 16 00:55 test
  32. -rwxrwxr-x 1 yiltoncent yiltoncent 257 12月 16 00:54 touchfile.sh
  33. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls -s
  34. 总用量 28
  35. 4 dirent.c 8 dirent.o 12 test 4 touchfile.sh
  36. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ls test/
  37. 00 09 0i 0r 10 19 1i 1r 20 29 2i 2r 30 39 3i 3r 40 49 4i 4r 50 59 5i 5r 60 69 6i 6r 70 79 7i 7r 80 89 8i 8r 90 99
  38. 01 0a 0j 0s 11 1a 1j 1s 21 2a 2j 2s 31 3a 3j 3s 41 4a 4j 4s 51 5a 5j 5s 61 6a 6j 6s 71 7a 7j 7s 81 8a 8j 8s 91 9a
  39. 02 0b 0k 0t 12 1b 1k 1t 22 2b 2k 2t 32 3b 3k 3t 42 4b 4k 4t 52 5b 5k 5t 62 6b 6k 6t 72 7b 7k 7t 82 8b 8k 8t 92 9b
  40. 03 0c 0l 0u 13 1c 1l 1u 23 2c 2l 2u 33 3c 3l 3u 43 4c 4l 4u 53 5c 5l 5u 63 6c 6l 6u 73 7c 7l 7u 83 8c 8l 8u 93 9c
  41. 04 0d 0m 0v 14 1d 1m 1v 24 2d 2m 2v 34 3d 3m 3v 44 4d 4m 4v 54 5d 5m 5v 64 6d 6m 6v 74 7d 7m 7v 84 8d 8m 8v 94 9d
  42. 05 0e 0n 0w 15 1e 1n 1w 25 2e 2n 2w 35 3e 3n 3w 45 4e 4n 4w 55 5e 5n 5w 65 6e 6n 6w 75 7e 7n 7w 85 8e 8n 8w 95 9e
  43. 06 0f 0o 0x 16 1f 1o 1x 26 2f 2o 2x 36 3f 3o 3x 46 4f 4o 4x 56 5f 5o 5x 66 6f 6o 6x 76 7f 7o 7x 86 8f 8o 8x 96 9f
  44. 07 0g 0p 0y 17 1g 1p 1y 27 2g 2p 2y 37 3g 3p 3y 47 4g 4p 4y 57 5g 5p 5y 67 6g 6p 6y 77 7g 7p 7y 87 8g 8p 8y 97
  45. 08 0h 0q 0z 18 1h 1q 1z 28 2h 2q 2z 38 3h 3q 3z 48 4h 4q 4z 58 5h 5q 5z 68 6h 6q 6z 78 7h 7q 7z 88 8h 8q 8z 98

测试的结果确实与计算结果一致。

未解之谜

检查本机的/usr/include/i386-linux-gnu/bits/dirent.h目录项结构体,具体内容如下。

 
  1. struct dirent
  2. {
  3. #ifndef __USE_FILE_OFFSET64
  4. __ino_t d_ino;
  5. __off_t d_off;
  6. #else
  7. __ino64_t d_ino;
  8. __off64_t d_off;
  9. #endif
  10. unsigned short int d_reclen;
  11. unsigned char d_type;
  12. char d_name[256]; /* We must not include limits.h! */
  13. };

我编了小程序以确定struct dirent的大小:

 
  1. #include <dirent.h>
  2. #include <stdio.h>
  3.  
  4. int main(void)
  5. {
  6. printf("struct dirent length: %d\n",sizeof(struct dirent));
  7. return 0;
  8. }

编译运行的结果:

 
  1. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ gcc -o dirent.o dirent.c
  2. yiltoncent@yiltoncent-GA-MA785GM-US2H:~/dirtest$ ./dirent.o
  3. struct dirent length: 268

其中d_name项的大小为256,而上面的四项的实际大小为4+4+2+1=11,加起来267≠268呀?!这是因为系统4字节对齐所致。

<think>好的,我现在需要回答用户在Linux系统中创建文件时的底层机制,包括目录文件名和inode的相关问题。首先,我需要回顾自己已有的知识,并查阅提供的引用内容,确保信息准确。 用户的问题涉及创建文件的底层过程,特别是目录文件名和inode的关系。根据引用[1]和[2],目录(dentry)是连接文件名和inode的结构。每个目录包含文件名和对应的inode号,以及其他元数据。创建文件时,系统会在目录中新增一个目录,指向新文件的inode。 接下来,inode的作用是什么?inode存储文件的元数据,如权限、大小、时间戳以及数据块的指针。创建文件时,系统会分配一个空闲的inode,并填充相关信息。引用[4]提到,VFS通过dentry缓存目录结构,加速文件访问。因此,创建文件后,新的dentry会被添加到内存中的目录结构里。 文件名生成方面,当用户指定文件名时,系统会检查目录中是否已存在同名文件。如果不存在,则允许创建。如果用户没有指定名称,可能需要由应用程序生成唯一文件名,但底层系统调用通常需要显式名称。 步骤可能包括:检查权限,分配inode,更新目录,写入数据等。引用[3]提到目录本身也是文件,其内容是该目录下的dentry条目。因此,创建文件时,需要更新所在目录文件内容,即添加新的目录。 可能的问题点:如何处理inode耗尽的情况?引用[5]提到使用find清理文件来解决inode满的问题。创建文件时,若inode不足,会失败,用户需要清理磁盘或增加inode数量。 需要确保回答覆盖用户提到的各个部分:目录文件名生成、inode分配,以及底层机制中的步骤。同时,结合提供的引用,特别是关于dentry和inode的关系,以及目录作为文件的结构。 最后,生成相关问题,可能需要涉及性能、优化、应用场景或故障处理,如inode耗尽的情况。</think>在Linux系统中,创建文件的底层机制涉及文件系统目录(dentry)、inode和文件名的协同工作。以下是分步说明: --- ### 1. **权限检查与路径解析** 当用户调用`open()`或`creat()`系统调用时,内核首先检查目标目录的写权限[^3]。随后,根据文件路径逐级解析: - 从根目录(inode号为0)开始[^4],通过目录文件内容中的`dentry`映射,依次查找每一级目录的inode。 - 路径解析依赖内存中的`dentry`缓存树,加速访问[^4]。 --- ### 2. **分配inode与数据块** - **inode分配**:文件系统在磁盘的inode表中找到一个空闲inode,并初始化元数据(如权限、时间戳、大小等)[^2][^4]。 - **数据块分配**:根据文件大小,从块位图中找到空闲数据块,记录到inode的数据块指针中。 --- ### 3. **创建目录(dentry)** - **目录文件更新**:在目标目录文件中添加新的目录,包含`文件名`和分配的`inode编号`[^1][^2]。 - **内存缓存更新**:将新dentry加入内存的dentry树,立父子节点关系(例如父目录dentry指向新文件dentry)[^4]。 --- ### 4. **文件名与inode的绑定** - 文件名仅作为目录中的逻辑名称,实际文件操作通过inode实现。多个文件名(硬链接)可指向同一inode[^1]。 - 文件删除时,仅减少inode的链接计数,链接数为0且无进程占用时,inode和数据块才被释放[^1][^3]。 --- ### 5. **示例流程(代码层面)** ```c // 简化版系统调用流程 int fd = open("/home/user/newfile.txt", O_CREAT | O_WRONLY, 0644); write(fd, "Hello", 5); close(fd); ``` 1. `open()`触发路径解析、权限检查。 2. 分配inode,更新目录文件。 3. `write()`将数据写入inode指向的数据块。 4. `close()`更新inode的元数据(如修改时间)。 --- ### 关键概念总结 | 组件 | 作用 | |-----------|----------------------------------------------------------------------| | **inode** | 存储文件元数据及数据块位置,唯一标识文件实体[^2][^4]。 | | **dentry** | 内存中缓存的目录结构,映射文件名到inode,加速路径解析[^3][^4]。 | | **目录文件** | 存储目录下所有文件的dentry条目,本质是一种特殊文件[^2][^3]。 | ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值