文件过多时ls命令为什么会卡住?
不知道你有没有遇到过当一个文件夹下文件特别多,在下面执行
ls
命令的时候要等好长时间才能展现出来的问题?如果有,你有想过这是为什么吗,我们该如何解决? 要想深入理解这个的问题产生的原因,我们就需要从文件夹占用的磁盘空间开始讨论了。
inode消耗验证
在 《新建一个空文件占用多少磁盘空间?》 中我提到了每一个文件会消耗其所在文件夹中的一点空间。文件夹呢,其实也一样会消耗inode的。 我们先看一下当前inode的占用情况
# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
......
/dev/sdb1 2147361984 12785020 2134576964 1% /search
再创建一个空文件夹
# mkdir temp
# df -i
Filesystem Inodes IUsed IFree IUse% Mounted on
......
/dev/sdb1 2147361984 12785021 2134576963 1% /search
通过IUsed可以看到,
和空文件一样,空的文件夹也会消耗掉一个inode
。不过这个很小,我的机器上才是256字节而已,应当不是造成
ls
命令卡主的元凶。
block消耗验证
文件夹的名字存在哪儿了呢?嗯,和
《新建一个空文件占用多少磁盘空间?》
里的文件类似,会消耗一个
ext4_dir_entry_2
(今天用ext4举例,它在linux源码的fs/ext4/ex4.h文件里定义),放到其父目录的block里了。根据这个,相信你也很快能想到,如果它自己节点下创建一堆文件的话,就会占用它自己的block。我们来动手验证一下:
# mkdir test
# cd test
# du -h
4.0K .
这里的4KB就表示消耗掉了一个block。 空文件不消耗block,空目录为啥一开始就消耗block了呢,那是因为其必须默认带两个目录项"."和".."。另外这个4K在你的机器上不一定是这么大,它其实是一个block size,在你格式化的时候决定的。
我们再新建两个空的文件,再查看一下:
# touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab
# touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
# du -h
4.0K .
貌似,没有什么变化。这是因为
- 第一、新的空文件不占用block,所以这里显示的仍然是目录占用的block。
- 第二、之前文件夹创建时候分配的4KB里面空闲空间还有,够放的下这两个文件项
那么我再多创建一些试试,动用脚本创建100个文件名长度为32Byte的空文件。
#!/bin/bash
for((i=1;i<=100;i++));
file="tempDir/"$(echo $i|awk '{printf("%032d",$0)}')
echo $file
touch $file
# du -h
12K .
哈哈,这时我们发现目录占用的磁盘空间变大了,成了3个Block了。当我们创建到10000个文件的时候,
# du -h
548K .
在每一个
ext4_dir_entry_2
里都除了文件名以外,还记录着inode号等信息,详细定义如下:
struct ext4_dir_entry_2 {
__le32 inode; /* Inode number */
__le16 rec_len; /* Directory entry length */