2

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

4

1 回答 1

6

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

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

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

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

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

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

但问题是在内核内部的另一边实际发生了什么:

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

Cgroup 是一个特殊的文件系统,当它添加一个文件(使用kernel/cgroup.ccgroup_add_file中定义的函数)时,它总是将大小 0 传递给,因此 /sys/fs/cgroups 中的任何文件(由 cgroup fs 创建)都会无论文件的实际内容如何,​​它的大小始终为零。__kernfs_create_file

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

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

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

Cgroup fs 具有在其文件中生成数据的功能。这是在kernel/cgroup.ctasks中定义文件的方式

{
        .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 是否还有任务,更简单的方法是在发布时使用通知。

来自文档/cgroup-v1/cgroups.txt

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

于 2017-01-06T23:17:32.323 回答