在linux中,文件不为空,但大小为0

时间:2016-12-09 02:40:41

标签: shell file cgroups

我测试Shell中的文件是否为空。 test -s /sys/fs/cgroup/systemd/docker/d4e311735706485e748513bad611070e223cba76fdf4c72a1102d14b653da750/tasks 它返回false,当我使用ls -lh时我发现它的大小为0,但是当我使用cat时,我可以在此文件中获得4071,这意味着该文件不为空。我想也许这个文件太小了,我在我的主目录中创建了一个文件,然后回显4071,我发现它的大小不是0. / sys / fs / cgroup中的文件是特殊的吗?

1 个答案:

答案 0 :(得分:1)

您正在处理的文件是一个特殊文件,它是cgroup文件系统的一部分。

要理解为什么会发生这种情况,让我们看看当你test -e $filename时会发生什么。

我们将使用strace命令打印命令所执行的系统调用。

如果你strace test -e $filename,你会在结果中找到这一行:

stat("$filename", {st_mode=S_IFREG|0644, st_size=0, ...}) = 0

在这种情况下,它返回st_size = 0,这是文件的大小。

但问题是内核中实际发生的事情:

当您尝试处理文件时,您会进行系统调用,该调用将进入内核中称为虚拟文件系统的中间层,而后者又会调用负责所需信息的部分。统计系统调用将尝试从与文件对应的inode中获取状态。文件系统可以根据需要创建和操作inode。

Cgroup是一个特殊的文件系统,当它添加一个文件时(使用kernel/cgroup.c中定义的cgroup_add_file函数),它总是将大小0传递给__kernfs_create_file,这就是为什么里面的任何文件/ sys / fs / cgroups(由cgroup fs创建)将始终具有关于文件实际内容的零大小。

对于另一部分,当cat文件时。如果你做strace cat $filename,那就是你将得到的:

open("$filename", O_RDONLY)                     = 3
read(3, "...", 131072)                          = ###

读取系统调用将通过虚拟文件系统进入内核文件系统,并使用与该文件关联的文件操作,它将为您提供所需的数据。

Cgroup fs具有在其文件中生成数据的功能。这就是kernel/cgroup.c

中定义tasks文件的方式
{
        .name = "tasks",
        .seq_start = cgroup_pidlist_start,
        .seq_next = cgroup_pidlist_next,
        .seq_stop = cgroup_pidlist_stop,
        .seq_show = cgroup_pidlist_show,
        .private = CGROUP_FILE_TASKS,
        .write = cgroup_tasks_write,
},

所以seq_start,seq_next,seq_stop和seq_show是负责生成文件所需信息的函数。您可以轻松前往kernel/cgroups.c并查看他们的操作。

请注意,如果您想知道cgroup是否还有任务,更简单的方法是在发布时使用通知。

来自Documentation/cgroup-v1/cgroups.txt

  

如果在cgroup中启用了notify_on_release标志(1),那么每当cgroup中的最后一个任务离开(退出或附加到某个其他cgroup)并且该cgroup的最后一个子cgroup被删除时,内核就会运行由该层次结构的根目录中的“release_agent”文件的内容指定的命令,提供废弃的cgroup的路径名(相对于cgroup文件系统的安装点)。这样可以自动删除已放弃的cgroup。系统引导时根cgroup中的notify_on_release的默认值被禁用(0)。创建时其他cgroup的默认值是其父级的notify_on_release设置的当前值。 cgroup层次结构的release_agent路径的默认值为空。