[关闭]
@yiltoncent 2015-12-15T17:01:29.000000Z 字数 3986 阅读 890

一个4KB的目录能最多可以包含多少个文件?

LINUX filesystem


新建目录也有大小

我们知道,在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. if [ -d $1 ]; then
  3. cd $1
  4. fi
  5. 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"
  6. count=0
  7. for x in $chrs
  8. do
  9. for y in $chrs
  10. do
  11. let count=count+1
  12. if [ $count -gt $2 ]; then
  13. exit
  14. fi
  15. touch $x$y
  16. done
  17. 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. int main(void)
  4. {
  5. printf("struct dirent length: %d\n",sizeof(struct dirent));
  6. return 0;
  7. }

编译运行的结果:

  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字节对齐所致。
那么,如果按照上面脚本的做法,生成的文件文件名大小会超过2,那么每个文件的目录项大小就是13,按照四字节对齐就是16字节,最大存储文件记录的个数为4096/16=256。可是实验结果并不支持上述推论。
目前尚且不知道原因为何?希望知道的同学能联系我,帮我解惑答疑。

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注