apue课后题4.7在运行图 4-16 的程序时,使用了 df(1) 命令来检查空闲的磁盘空间,为什么不使用 du(1) 命令?
这里首先介绍下du和df的区别,再回答上面的问题。

1) du == Disk Usage
How much disk space is being used by these files?

2) df == Disk Free
How much free disk space do we have?

参考stackoverflow
这里有个非常经典的答案:

You most probably know that you can remove a file that still in use by some application and for this application it remains available. It because file descriptor in /proc/ filesystem is held open.
So if there are such open descriptors to files already removed, space occupied by them considered as used by df (and df is right), but they can not be taken into account by du due to there are no longer filenames associated with them.
You can find all unlinked but held open files with:
# lsof | grep '(deleted)'

结合apue中的代码,我们来实际验证这个区别。
umask.c

#include "apue.h"
#include <fcntl.h>

int
main(void)
{
    if (open("tempfile", O_RDWR) < 0)
        err_sys("open error");
    if (unlink("tempfile") < 0)
        err_sys("unlink error");
    printf("file unlinked\n");
    sleep(15);
    printf("done\n");
    exit(0);
}

首先我们构造一个比较大点的tempfile

[root filedir]#cat /root/apue.3e/*/*.c > tempfile
[root filedir]#cat /root/apue.3e/*/*.c >> tempfile
[root filedir]#cat /root/apue.3e/*/*.c >> tempfile
[root filedir]#cat /root/apue.3e/*/*.c >> tempfile
[root filedir]#ll tempfile
-rw-r--r--. 1 root root 1103572 7月  24 11:25 tempfile
[root filedir]#cat /root/apue.3e/*/*.c >> tempfile
[root filedir]#cat /root/apue.3e/*/*.c >> tempfile
[root filedir]#cat /root/apue.3e/*/*.c >> tempfile
[root filedir]#
[root filedir]#ll tempfile
-rw-r--r--. 1 root root 1931251 7月  24 11:26 tempfile
[root filedir]#cp tempfile tempfile.bak

然后按照书中的方式运行:

[root filedir]#df /root/apue.3e/filedir/
文件系统                   1K-块    已用     可用 已用% 挂载点
/dev/mapper/centos-root 52403200 8602808 43800392   17% /
[root filedir]#
[root filedir]#./unlink &
[1] 6699
[root filedir]#file unlinked

[root filedir]#df /root/apue.3e/filedir/
文件系统                   1K-块    已用     可用 已用% 挂载点
/dev/mapper/centos-root 52403200 8602808 43800392   17% /
[root filedir]#
[root filedir]#df /root/apue.3e/filedir/
文件系统                   1K-块    已用     可用 已用% 挂载点
/dev/mapper/centos-root 52403200 8602808 43800392   17% /
[root filedir]#
[root filedir]#df /root/apue.3e/filedir/
文件系统                   1K-块    已用     可用 已用% 挂载点
/dev/mapper/centos-root 52403200 8602808 43800392   17% /
[root filedir]#done

[1]+  完成                  ./unlink
[root filedir]#df /root/apue.3e/filedir/
文件系统                   1K-块    已用     可用 已用% 挂载点
/dev/mapper/centos-root 52403200 8598968 43804232   17% /

unlink函数只有当链接计数打到0时,文件的内容才可被删除。只要有进程打开了该文件,就会阻止删除文件的内容。这一特性经常被程序用来确保即使是在程序崩溃时,它所创建的临时文件也不会遗留下来,进程调用open或creat创建一个文件,然后立即调用unlink,因为该文件依旧是打开的,所以不会将其内容删除。只有当进程关闭该文件或终止时,该文件的内容才会被删除。

关于上面的内容可以使用如下命令验证:
查看已经unlinked,但是被打开的文件的方法:

在程序结束sleep前执行lsof | grep '(deleted)'| grep tempfile
[root filedir]#lsof | grep '(deleted)'| grep tempfile
unlink     6766                 root    3u      REG              253,0   1931251   36932488 /root/apue.3e/filedir/tempfile (deleted)
[root filedir]#done

这也就是说我们不能使用du命令验证unlink这一特性,实际验证结果如下:

[root filedir]#du .
3980    .
[root filedir]#./unlink &
[1] 6813
[root filedir]#file unlinked

[root filedir]#du .
2092    .

du命令依赖于文件,文件不存在,但实际上还会占用空间,因此书中的这个例子需要使用df命令查看。