![为什么从 tmpfs 中删除大文件不是即时的?](https://linux22.com/image/82595/%E4%B8%BA%E4%BB%80%E4%B9%88%E4%BB%8E%20tmpfs%20%E4%B8%AD%E5%88%A0%E9%99%A4%E5%A4%A7%E6%96%87%E4%BB%B6%E4%B8%8D%E6%98%AF%E5%8D%B3%E6%97%B6%E7%9A%84%EF%BC%9F.png)
$ cat /proc/mounts | egrep ' /tmp '
tmpfs /tmp tmpfs rw,nosuid,nodev,relatime 0 0
$ dd if=/dev/zero bs=1M count=3000 of=/tmp/q
3000+0 records in
3000+0 records out
3145728000 bytes (3.1 GB) copied, 1.04961 s, 3.0 GB/s
$ time rm /tmp/q
real 0m0.296s
user 0m0.000s
sys 0m0.290s
为什么不0.000s
?不涉及磁盘,只是标记内存不再使用。
答案1
“将该内存标记为未使用”是系统调用必须完成的工作量的函数unlinkat(2)
,而该工作量又随文件的大小线性缩放。对于tmpfs
内存约为 4G 的 RHEL 6 系统上的默认情况,可以按如下方式进行演示。
$ sudo mkdir /tmpfs; sudo mount -t tmpfs -o size=75% tmpfs /tmpfs; cd /tmpfs
$ dd if=/dev/zero bs=1M of=blah count=2859
...
$ strace -c rm blah 2>&1 | head -3
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.241964 241964 1 unlinkat
$ for c in 500 1000 1500 2000 2500; do dd if=/dev/zero bs=1M of=blah count=$c 2>/dev/null; echo -n "$c "; strace -c rm blah 2>&1 | awk '/unlinkat/{print $3}'; done
500 53992
1000 88986
1500 135980
2000 174974
2500 222966
至于unlinkat(2)
系统调用具体在做什么,这需要深入研究源代码;我的猜测是,当文件被删除时,表示内存中文件的数据结构(链接列表?)正在循环,从而解释了操作时间随文件大小的线性增长。