httppostedfilebase.saveas后文件被占用_文件过多时ls命令为什么会卡住?
不知道你有没有遇到过当一个文件夹下文件特别多,在下面执行ls
命令的时候要等好长时间才能展现出来的问题?如果有,你有想过这是为什么吗,我们该如何解决? 要想深入理解这个的问题产生的原因,我们就需要从文件夹占用的磁盘空间开始讨论了。
1inode消耗验证
在《新建一个空文件占用多少磁盘空间?》中我提到了每一个文件会消耗其所在文件夹中的一点空间。文件夹呢,其实也一样会消耗inode的。 我们先看一下当前inode的占用情况
# df -i Filesystem Inodes IUsed IFree IUse% Mounted on....../dev/sdb1 2147361984 12785020 2134576964 1% /search
再创建一个空文件夹
# mkdir temp# df -iFilesystem Inodes IUsed IFree IUse% Mounted on....../dev/sdb1 2147361984 12785021 2134576963 1% /search
通过IUsed可以看到,和空文件一样,空的文件夹也会消耗掉一个inode。不过这个很小,我的机器上才是256字节而已,应当不是造成ls
命令卡住的元凶。
2block消耗验证
文件夹的名字存在哪儿了呢?嗯,和《新建一个空文件占用多少磁盘空间?》里的文件类似,会消耗一个ext4_dir_entry_2
(今天用ext4举例,它在linux源码的fs/ext4/ex4.h文件里定义),放到其父目录的block里了。根据这个,相信你也很快能想到,如果它自己节点下创建一堆文件的话,就会占用它自己的block。我们来动手验证一下:
# mkdir test# cd test # du -h4.0K .
这里的4KB就表示消耗掉了一个block。 空文件不消耗block,空目录为啥一开始就消耗block了呢,那是因为其必须默认带两个目录项"."和".."。另外这个4K在你的机器上不一定是这么大,它其实是一个block size,在你格式化的时候决定的。
我们再新建两个空的文件,再查看一下:
# touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaab# touch aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa# du -h4.0K .
貌似,没有什么变化。这是因为
第一、新的空文件不占用block,所以这里显示的仍然是目录占用的block。
第二、之前文件夹创建时候分配的4KB里面空闲空间还有,够放的下这两个文件项
那么我再多创建一些试试,动用脚本创建100个文件名长度为32Byte的空文件。
#!/bin/bashfor((i=1;i<=100;i++));dofile="tempDir/"$(echo $i|awk '{printf("%032d",$0)}') echo $file touch $filedone# du -h12K .
哈哈,这时我们发现目录占用的磁盘空间变大了,成了3个Block了。当我们创建到10000个文件的时候,
# du -h548K .
在每一个ext4_dir_entry_2
里都除了文件名以外,还记录着inode号等信息,详细定义如下:
struct ext4_dir_entry_2 { __le32 inode; /* Inode number */ __le16 rec_len; /* Directory entry length */ __u8 name_len; /* Name length */ __u8 file_type; char name[EXT4_NAME_LEN]; /* File name */};
我们计算一下,平均每个文件占用的空间=548K/10000=54字节。也就是说,比我们的文件名32字节大一点点,基本对上了。 这里我们也领会到一个事实,文件名越长,在其父目录中消耗的空间也会越大。
3本文结论
一个文件夹当然也是要消耗磁盘空间的。
首先要消耗掉一个inode,我的机器上它是256字节
需要消耗其父目录下的一个目录项
ext4_dir_entry_2
,保存自己inode号,目录名。其下面如果创建文件夹或者文件的话,它就需要在自己的block里
ext4_dir_entry_2
数组
目录下的文件/子目录越多,目录就需要申请越多的block。另外ext4_dir_entry_2
大小不是固定的,文件名/子目录名越长,单个目录项消耗的空间也就越大。
对于开篇的问题,我想你现在应该明白为什么了,问题出在文件夹的block身上。 这就是当你的文件夹下面文件特别多,尤其是文件名也比较长的时候,它会消耗掉非常多的block。当你遍历文件夹的时候,如果Page Cache中没有命中你要访问的block,就会穿透到磁盘上进行实际的IO。在你的角度来看,就是你执行完ls
后,卡住了。
那么你肯定会问,我确实要保存许许多多的文件,我该怎么办? 其实也很简单,多创建一些文件夹就好了,一个目录下别存太多,就不会有这个问题了。工程实践中,一般的做法就是通过一级甚至是二级hash把文件散列到多个目录中,把单目录文件数量控制在十万或万以下。
4ext的一个bug
貌似今天的实践应该结束了,现在让我们把刚刚创建的文件全部删掉,再看一下。
# rm -f *# du -h72K .
等等,什么情况?文件夹下的文件都已经删了,该文件夹为什么还占用72K的磁盘空间? 这个疑惑也伴随了我很长时间,后来才算是解惑。问题关键在于ext4_dir_entry_2
中的rec_len
。这个变量存储了当前整个ext4_dir_entry_2
对象的长度,这样操作系统在遍历文件夹的时候,就可以通过当前的指针,加上这个长度就可以找到文件夹中下一个文件的dir_entry
了。这样的优势是遍历起来非常方便,有点像是一个链表,一个一个穿起来的。 但是,如果要删除一个文件的话,就有点小麻烦了,当前文件结构体变量不能直接删,否则链表就断了。Linux的做法是在删除文件的时候,在其目录中只是把inode设置为0就拉倒,并没有回收整个ext4_dir_entry_2
对象。其实和大家做工程的时候经常用到的假删除是一个道理。现在的xfs文件系统好像已经没有这个小问题了,但具体咋解决的,暂时没有深入研究,如果你有答案,欢迎留言!
httppostedfilebase.saveas后文件被占用_文件过多时ls命令为什么会卡住?相关推荐
- linux批量命令卡住,关于linux:文件过多时ls命令为什么会卡住
不晓得你有没有遇到过当一个文件夹下文件特地多,在上面执行ls命令的时候要等好长时间能力展示进去的问题?如果有,你有想过这是为什么吗,咱们该如何解决? 要想深刻了解这个的问题产生的起因,咱们就须要从文件 ...
- linux rec命令_文件过多时ls命令为什么会卡住?
不知道你有没有遇到过当一个文件夹下文件特别多,在下面执行ls命令的时候要等好长时间才能展现出来的问题?如果有,你有想过这是为什么吗,我们该如何解决? 要想深入理解这个的问题产生的原因,我们就需要从文件 ...
- 文件过多时ls命令为什么会卡住?
不知道你有没有遇到过当一个文件夹下文件特别多,在下面执行ls命令的时候要等好长时间才能展现出来的问题?如果有,你有想过这是为什么吗,我们该如何解决? 要想深入理解这个的问题产生的原因,我们就需要从文件 ...
- ipynb和py文件一样吗_文件描述符了解一下
作者 | 田伟然 回首向来萧瑟处,归去,也无风雨也无晴. 杏仁工程师,关注编码和诗词. 前言 文件描述符在unix系统中几乎无处不在 网络接口 select.poll.epoll 涉及到文件描述符 ...
- channelsftp 上传文件为空_文件上传踩坑记及文件清理原理探究
目录 1. 糟糕的异步存储文件实现 2. 异常原因推理 3. 问题解决方式 4. spring清理文件原理 5. tomcat清理文件原理 最近搞一个文件上传功能,由于文件太大,或者说其中包含了比较多 ...
- 拷贝文件不移动_在不使用 mv 命令的情况下移动文件
有时当你需要移动一个文件时,mv 命令似乎不是最佳选项,那么你会如何做呢? -- Seth Kenlon(作者) 不起眼的 mv 命令是在你见过的每个 POSIX 系统中都能找到的有用工具之一.它的作 ...
- jsp文件上传_文件上传
一.文件上传的目的--脚本文件 文件上传的一共可造成三种危害,从低到高分别是,任意内容文件,html文件,脚本文件. 任意内容文件 任意内容文件指的是虽然文件后缀不可控,但是文件内容可控,比如我可以上 ...
- python引入文件并执行_文件操作和导入os模块执行文件和目录管理操作
文件概念以及文本文件和二进制文件的区别 计算机的CPU如果想要访问保存在磁盘上的文件,第一步需要把磁盘上的文件数据加载到内存中.因为内存的读写速度要比磁盘的读写速度快很多. 计算机只能识别0101这种 ...
- java上传文件的二进制_文件的上传:二进制文件的上传;
***二进制文件上传的方法: ***在lib目录下:导入文件上传的开源架包:commons-fileupload-1.2.1.jar,commons-io-2.0.jar: 建立Servlet类:Up ...
最新文章
- java 0b,java 1.6.0_38-b05 vm 20.13-b02优化手记
- nginx配置thinkphp5
- Protobuf之proto文件编写规则
- Water Balance CodeForces - 1300E
- mysql命令导出数据库_MYSQL 数据库导入导出命令
- Python3之字典生成器结合lambda实现按key/value排序
- 背包问题 codevs2210 数字组合
- java servlet是单例吗_Servlet是单例的吗?
- 查看pytorch和匹配的CUDA版本
- WLC HA (for AP)?
- .NET基础 (04)基础类型和语法
- GraphPB:Graphical representations of prosody boundary in speech synthesis论文阅读
- SLAM常见面试题集锦
- VirusTotal智能搜索安卓样本示例
- matlab中clear;close;clc的作用说明
- Robust continuous clustering
- 1.大数据之EKL平台搭建以及使用
- 【每日面试】2021政采云Java一面
- 数据、数据项、数据结构
- 告别高墙铁窗,AI或将终结传统监狱模式
热门文章
- 大数据学习线路_[个人经验篇]大数据学习线路前导篇
- 邯郸学院计算机科学与技术录取分,邯郸学院录取分数线2021是多少分(附历年录取分数线)...
- php中ajax方法的理解,基本的PHP和AJAX
- php 6位邮政编码,php / mysql邮政编码邻近搜索
- 康宁玻璃ct值计算公式_防眩光玻璃的硬度及强度
- 旺财速啃H5框架之Bootstrap(六)
- javascript使用闭包模拟私有属性和方法
- LeetCode: Word Ladder
- 名校和非名校[两个实习生的事]
- [美丽的烦恼] SQL删除某些字段重复的记录(只保留一条)