磁盘空间检查是个常见的小功能,但它的数字在不同文件系统上含义不同:稀疏文件、克隆、共享容器、只读挂载。这篇用真实挂载的小镜像,把 FileStore 返回什么、写满时发生什么逐项量出来。
[basic]
APFS 数据卷上的临时目录:
name=/dev/disk3s1 type=apfs readOnly=false block=4096 total=471482.1 MB usable=22332.2 MB unallocated=22332.2 MB
属性视图:Basic=true Posix=true FileOwner=true Dos=false Acl=false UserDefined=true
toString = /System/Volumes/Data (/dev/disk3s1)
HFS+ 镜像(本次挂载):
name=/dev/disk7s1 type=hfs readOnly=false block=4096 total=20.0 MB usable=19.5 MB unallocated=19.5 MB
属性视图:Basic=true Posix=true FileOwner=true Dos=false Acl=false UserDefined=true
toString = <实验目录> (/dev/disk7s1)
FAT32 镜像(本次挂载):
name=/dev/disk8s1 type=msdos readOnly=false block=512 total=63.0 MB usable=63.0 MB unallocated=63.0 MB
属性视图:Basic=true Posix=true FileOwner=true Dos=false Acl=false UserDefined=true
toString = <实验目录> (/dev/disk8s1)
根目录 /:
name=/dev/disk3s3s1 type=apfs readOnly=true block=4096 total=471482.1 MB usable=22332.2 MB unallocated=22332.2 MB
属性视图:Basic=true Posix=true FileOwner=true Dos=false Acl=false UserDefined=true
toString = / (/dev/disk3s3s1)
Files.getFileStore("/etc")(符号链接,指向 private/etc):name=/dev/disk3s1 type=apfs readOnly=false block=4096 total=471482.1 MB usable=22332.2 MB unallocated=22332.2 MB
不存在的路径:NoSuchFileException: /var/folders/km/b69gr9cs3dv8qsm8rjjb4qqc0000gn/T/fs12874453109841403756/nope
同一个存储的两个对象 equals? true;tmp 与根目录的 store equals? false
df -k 对照(1 KB 块):
Filesystem 1024-blocks Used Available Capacity iused ifree %iused Mounted on
/dev/disk7s1 20440 476 19964 3% 2 4294967277 0% <实验目录>
/dev/disk8s1 64511 1 64510 1% 0 0 - <实验目录>
/dev/disk3s3s1 482797652 13756336 22868176 38% 484014 228681760 0% /
/dev/disk3s1 482797652 416448532 22868176 95% 3134703 228681760 1% /System/Volumes/Data [stores]
/ (/dev/disk3s3s1) type=apfs readOnly=true total=471482.1 MB
/dev (devfs) type=devfs readOnly=false total=0.2 MB
/System/Volumes/VM (/dev/disk3s6) type=apfs readOnly=false total=471482.1 MB
/System/Volumes/Preboot (/dev/disk3s4) type=apfs readOnly=false total=471482.1 MB
/System/Volumes/Update (/dev/disk3s2) type=apfs readOnly=false total=471482.1 MB
/System/Volumes/xarts (/dev/disk1s2) type=apfs readOnly=false total=500.0 MB
/System/Volumes/iSCPreboot (/dev/disk1s1) type=apfs readOnly=false total=500.0 MB
/System/Volumes/Hardware (/dev/disk1s3) type=apfs readOnly=false total=500.0 MB
/System/Volumes/Data (/dev/disk3s1) type=apfs readOnly=false total=471482.1 MB
/System/Volumes/Data/home (map auto_home) type=autofs readOnly=false total=0.0 MB
/System/Volumes/Update/SFR/mnt1 (/dev/disk2s1) type=apfs readOnly=false total=5120.0 MB
/System/Volumes/Update/mnt1 (/dev/disk3s3) type=apfs readOnly=false total=471482.1 MB
/Library/Developer/CoreSimulator/Volumes/iOS_23F77 (/dev/disk6s1) type=apfs readOnly=true total=17246.0 MB
<实验目录> (/dev/disk7s1) type=hfs readOnly=false total=20.0 MB
<实验目录> (/dev/disk8s1) type=msdos readOnly=false total=63.0 MB
共 15 个 FileStore
mount 命令的行数: 15 [fill]
HFS+ 镜像(20.0 MB)写入前 usable = 19.5 MB
循环写 40 个 1 MB:写入 19.0 MB;错误:IOException: No space left on device
写满后 usable = 0.5 MB;文件 size = 19.0 MB;unallocated = 0.5 MB
再创建一个小文件:<实验目录>
删除后 usable = 19.5 MB
预检查的陷阱:检查 usable = 19.5 MB 是否 >= 10 MB → true;但随后写 30 MB 仍会失败:IOException: No space left on device
FAT32 镜像(63.0 MB)usable = 63.0 MB;写 10 MB 之后 usable = 53.0 MB [fat]
FAT32 的属性视图:Basic=true Posix=true FileOwner=true Dos=false Acl=false UserDefined=true
读取 posix 权限:rwx------(macOS 的 msdos 挂载在 Java 里仍能看到 posix 视图)
用小写名字访问:Files.exists(hello.txt) = true;目录里的名字 = [t.bin, ._t.bin, Hello.TXT, ._Hello.TXT]
创建符号链接:<实验目录>
创建以冒号命名的文件 a:b → <实验目录>
创建 300 字符长文件名 → FileSystemException: <实验目录> 个 x): File name too long
文件修改时间的精度:写入时间 16921 ms;读回 lastModified % 2000 = 0(FAT 的时间戳 2 秒精度,取模为 0 说明已被截断到偶数秒)
setLastModifiedTime(…001.123 s) 读回 1700000000000 ms
对照 HFS+:setLastModifiedTime(…001.123 s) 读回 1700000001000 ms [sparse]
创建 2 GB 的文件(setLength)后:size = 2048.0 MB;usable 变化 0.0 MB(稀疏,没有分配)
du -k 显示实际占用:0 KB
写入 100 MB 随机数据后:size = 100.0 MB;usable 变化 -100.0 MB;du -k = 102400 KB
删除 100 MB 文件后 usable 回升 100.0 MB
200 MB 文件:cp -c(APFS 克隆)成功,usable 变化 0.0 MB;普通 cp 成功,usable 变化 -200.0 MB;三个文件 size 都是 200.0 MB / 200.0 MB / 200.0 MB
改写克隆文件的前 50 MB 之后 usable 再变化 -49.9 MB(写时复制:只有被改写的部分才占新空间) [file]
File.getTotalSpace / getFreeSpace / getUsableSpace = 471482.1 MB / 22332.2 MB / 22332.2 MB;FileStore 的 total / unallocated / usable = 471482.1 MB / 22332.2 MB / 22332.2 MB
不存在的路径:new File(nope).getFreeSpace() = 0(返回 0,不抛异常);Files.getFileStore(nope) → NoSuchFileException: /var/folders/km/b69gr9cs3dv8qsm8rjjb4qqc0000gn/T/fs14955048116493975500/nope
根分区 / 的 usable = 22332.2 MB,Data 卷 /System/Volumes/Data 的 usable = 22332.2 MB,/System/Volumes/VM = 22332.2 MB
getUsableSpace 与 getFreeSpace 差:0.0 MB(APFS 上两者相等,没有为非特权用户另外保留空间)
同一个 APFS 容器里不同卷共享空闲空间:Data 卷 unallocated = 22332.2 MB,VM 卷 unallocated = 22332.2 MB,根(/)= 22332.2 MB [ro]
只读挂载的 HFS+:isReadOnly = true;usable = 19.5 MB;total = 20.0 MB
写文件:FileSystemException: <实验目录> Read-only file system
创建目录:FileSystemException: <实验目录> Read-only file system
删除已有文件:FileSystemException: <实验目录> Read-only file system
读已有文件:hello
Files.isWritable(dir) = false(只读文件系统上返回什么)
根卷 /:isReadOnly = true;写 /x.txt → FileSystemException: /x.txt: Read-only file system
收尾:镜像已卸载? True