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