現在アクセス中のプロセスでそのファイルが開いていることを確認するために、要求に応じてクエリを実行するファイルがあるとします。すべてのPIDを繰り返すのは/proc/{PID}/fd
リソース集約的なようです。同じことを行う他の方法はありますか?
答え1
これを実行できるツールは次のとおりです。fuser
(出力PIDのみ)とlsof
(多くのオプションと美しい出力)。
/proc/{PID}/fd のすべての PID を繰り返すのにリソースが多いようです。
とにかくこれがLinuxでは唯一の方法です。どのプロセスでファイルが開いているかを問い合わせるシステムコールはありません。しかし、直接これを実行しないでください。/proc/{PID}/fd
これは厳密に言えば、ファイルを開くだけであり、メモリマップされたファイル、ディレクトリを開くなどの他のケースはリストしないからです。
これは、ファイルを所有していてもルートで検索しない限り、他のユーザーとして実行されているプロセスがファイルを開くことができるかどうかわからないことを意味します。 (しかし、他のユーザーがファイルを見ることができず、ファイルが作成された後、またはシステムが再起動された後でもそのファイルを見ることができない場合、そのようなプロセスは存在しません。)
より一般的には、ユーザーが制御できないプロセスであり、これには、他の名前空間で実行されたり、追加の権限を持つプロセスなどの他の状況が含まれる場合があります。
答え2
使用lsof
。
たとえば、
[root@nagios01 objects]# lsof /var/lib/mysql/ib_logfile0
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 17699 mysql 9uW REG 8,3 5242880 4850251 /var/lib/mysql/ib_logfile0
他の例:
merlin@uc-s4m75657:~/Experiments/test_ifxr$ lsof -a .
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 8646 merlin cwd DIR 254,2 4096 421348 .
bash 9261 merlin cwd DIR 254,2 4096 421348 .
ssh 37456 merlin cwd DIR 254,2 4096 421348 .
bash 38639 merlin cwd DIR 254,2 4096 421348 .
lsof 38679 merlin cwd DIR 254,2 4096 421348 .
lsof 38680 merlin cwd DIR 254,2 4096 421348 .
ご覧のとおり、この場合、「現在のディレクトリ」(つまり、ポイントが指す場所)は6つのプロセスによって要求されます。
最後の例はまた、「PID」ではなく、同時に複数のPIDであってもよいことを示している。別の例は、複数のワーカープロセスから同時に読み取られることが多いPostgreSQLデータファイルです。
エディタでファイルを開くと、lsof出力には表示されません。たとえば、編集者はファイルをキャッシュし、開く/保存操作中にのみそのファイルに触れることができます。これはlsofに表示されます。
答え3
次の質問に対する私の意見に基づいて完全に終了していないプロセスを確認する必要がありますか?調査するテストコードを作成しました。
一部のスレッドが終了しました。別のスレッドを実行できるようにしながら、基本スレッドを終了させるプログラムのソースコード。
find_processes_using_file.clsof
ファイル名への参照を検索できるプログラムに似たソースコードです。コマンドラインオプションでは、次のことができます。
- 繰り返しPIDで検索
/proc/<pid>/fd
- 繰り返しTIDで検索
/proc/<pid>/task/<tid>/fd
テストハーネスの2つのインスタンスが起動しましたpartial_thread_exit
。これにより、/dev/shm/IBV_MESSAGE_BW_IN_USE
.first インスタンスと呼ばれる基本スレッドとは異なるスレッドが引き続き実行されます。
$ ./partial_thread_exit
Blocker_Task tid 17995 running in pid 17994
Main thread in pid 17994 - press return to exit main thread only
別のスレッドが1つだけ実行されるように、2番目のインスタンスを残します。つまり、基本スレッドが終了しました。
$ ./partial_thread_exit
Blocker_Task tid 13435 running in pid 13434
Main thread in pid 13434 - press return to exit main thread only
Main thread exiting...
PIDで検索を実行すると、通常のユーザーまたはrootとして実行しているかにかかわらず、メインスレッドで実行されているプロセスのみを見つけることができます。
$ time ./find_processes_using_file /dev/shm/IBV_MESSAGE_BW_IN_USE
/proc/17994/fd/3 -> /dev/shm/IBV_MESSAGE_BW_IN_USE
num_filenames_compared=2532 num_eacces_errors=260
real 0m0.019s
user 0m0.003s
sys 0m0.015s
$ time sudo ./find_processes_using_file /dev/shm/IBV_MESSAGE_BW_IN_USE
/proc/17994/fd/3 -> /dev/shm/IBV_MESSAGE_BW_IN_USE
num_filenames_compared=3435 num_eacces_errors=0
real 0m0.044s
user 0m0.011s
sys 0m0.031s
また、このオプションを使用してTIDで検索を実行すると、通常-t
のユーザーまたはrootとして実行しているかにかかわらず、メインスレッドを持つプロセスとメインスレッドが終了したプロセスを見つけることができます。
$ time ./find_processes_using_file -t /dev/shm/IBV_MESSAGE_BW_IN_USE
/proc/13434/task/13435/fd/3 -> /dev/shm/IBV_MESSAGE_BW_IN_USE
/proc/17994/task/17994/fd/3 -> /dev/shm/IBV_MESSAGE_BW_IN_USE
num_filenames_compared=68327 num_eacces_errors=317
real 0m0.254s
user 0m0.036s
sys 0m0.217s
$ time sudo ./find_processes_using_file -t /dev/shm/IBV_MESSAGE_BW_IN_USE
/proc/13434/task/13435/fd/3 -> /dev/shm/IBV_MESSAGE_BW_IN_USE
/proc/17994/task/17994/fd/3 -> /dev/shm/IBV_MESSAGE_BW_IN_USE
num_filenames_compared=69500 num_eacces_errors=0
real 0m0.280s
user 0m0.048s
sys 0m0.228s
予想通り、TIDで検索するのは、以下のようにPIDで検索するよりも遅くなります。
- より多くのリアルタイムレポート
time
- 報告されるより大きな値は、
num_filenames_compared
PID / TIDと一致する必要がある開いているファイルの数です。
明らかに、2つの間の絶対的な違いは、システムで実行されているTID / PIDの総数に依存します。
num_eacces_errors
通常のユーザーとして実行すると、PID / TIDのディレクトリを開く試みが失敗し、表示された場合、値は0ではありません。つまり、特定のプロセスでどのファイルを開いたかを確認する権限は何度もありませんか?fd
EACCES
答え4
カーネルには直接的な方法がないことを考慮すると、非常に原始的な方法があります。各ファイルが保存されているファイルシステムでは、pidになる可能性があるプロセス参照と参照カウントを作成する必要があります。これにはstruct inodeを変更することも含まれます。ただし、これには、参照とカウントをそれぞれ入力および削除する開始システム呼び出しと終了システム呼び出しを変更することが含まれます。構造体inodeは、現在の最後のアクセスや最後の変更タイムスタンプなどのタイムスタンプを維持し、この目的のために同じタイムスタンプを追跡できます。 fstatなどのシステムコールは、後でこのプロセス参照を返すように変更できます。これには、ファイルシステムやカーネルシステムコールを変更する必要があるなど、いくつかの欠点があります。ターゲットによって(組み込みデバイスの場合)、これが可能な場合があります。パブリックコールとシャットダウンコールによる参照の変更には同期が必要になる可能性があります。まれなケースを除いて、これは絶対に不可能です。これには、このパッチのカーネルアップグレードも含まれます。あまりにも多くのプロセスがファイルにアクセスし、参照リストが大きくなるなど、考慮する必要があるいくつかの要因があります。これはアプリケーション固有の問題です。