2016-12-09 5 views
1

シェルでファイルが空であるかどうかをテストします。 test -s /sys/fs/cgroup/systemd/docker/d4e311735706485e748513bad611070e223cba76fdf4c72a1102d14b653da750/tasks ls -lhを使用すると、falseが返され、サイズが0であることがわかりましたが、catを使用した場合、このファイルで4071が得られます。これはファイルが空でないことを意味します。私はおそらく、このファイルが小さすぎると思います、私は自分のホームディレクトリにファイルを作成し、それに4071をエコーすると、サイズが0ではないことがわかります。/ sys/fs/cgroupのファイルは特別ですか?Linuxではファイルが空ではないがサイズは0です

+0

は必ずしも「同時に」という意味ではありません。ファイルが書き込まれ、連続して切り捨てられることはありますか?それは普通のファイルですか、ls -l出力を表示できますか? –

+0

@Stefan Hegnyご回答いただきありがとうございます。ここにはls -lhの出力があります: '-rw-r-r-- 1 root root 0 12 11 15:47 tasks'私はあなたが正しいと思いますこのファイルはコンテナのプロセスを記録し、常に更新されます。 – cheon

+0

@ cheon少なくとも私はそれが「小さすぎる」の問題ではないと確信しています。コンピュータ言語のゼロ以上はゼロより大きく、他の「小さすぎる」層はありません。 –

答えて

1

処理しているファイルは、cgroupファイルシステムの一部である特別なファイルです。

これがなぜ起こるかを理解するために、test -e $filenameを実行するとどうなるかを見てみましょう。

straceコマンドを使用してシステムコールを出力するコマンドを使用します。

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

それはファイルのサイズであるst_size = 0を返します。この場合:あなたがstrace test -e $filenameを行う場合

は、あなたが結果にこの行を見つけます。

しかし、質問は実際にはカーネルの内部で、他の側に何が起こるかです:

ファイルに対処しようとすると、仮想と呼ばれるカーネルにおける中間層になり、システムコールを行いますファイルシステムは、必要な情報を担当する部分を呼び出します。 statシステムコールは、ファイルに対応するinodeから状態を取得しようとします。ファイルシステムは、必要に応じてiノードを作成し、操作することができます。それは、ファイルを(kernel/cgroup.cで定義されたcgroup_add_file関数を使用して)それは常に__kernfs_create_fileにサイズ0を通過する理由のcgroup FSによって作成された内部の任意のファイル/ SYSの/ fsの/のcgroup(その結果である追加するとき

のcgroupは、特殊なファイルシステムであります)は、ファイルの実際の内容に関して常にゼロサイズを持ちます。

他の部分については、ファイルcat。あなたがstrace cat $filenameを行う場合、それはあなたが得るものです:

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

readシステムコールはカーネルファイルシステムに仮想ファイルシステムを経由してファイルに関連付けられたファイル操作を使用します、それはあなたを取得します必要なデータ。

Cgroup fsには、ファイル内にデータを生成する機能があります。これは、tasksファイルはkernel/cgroup.c

{ 
     .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にまだタスクがあるかどうかを確認するには、リリース時にnotifyを使用するのが簡単な方法です。Documentation/cgroup-v1/cgroups.txt

から

notify_on_releaseフラグがcgroup内(1)有効になっている場合は、その都度のcgroupの葉の最後のタスクは、(終了またはいくつかの他のcgroupにアタッチ)とその最後の子のcgroup cgroupが削除されると、カーネルは、その階層のルートディレクトリにある "release_agent"ファイルの内容で指定されたコマンドを実行し、破棄されたcgroupのパス名(cgroupファイルシステムのマウントポイントからの相対パス)を指定します。これにより、放棄されたcgroupが自動的に削除されます。システム起動時のルートcgroupのnotify_on_releaseのデフォルト値は無効(0)です。作成時の他のcgroupのデフォルト値は、両親のnotify_on_release設定の現在の値です。 cgroup階層のrelease_agentパスのデフォルト値は空です。

関連する問題