web-dev-qa-db-ja.com

コマンドラインで信号を使用/送信する方法、任意のプログラム(例:dd)

ddプログラムのマンページを理解しようとしています。

実行中の「dd」プロセスにUSR1シグナルを送信すると、I/O統計が標準エラーに出力され、コピーが再開されます。

         $ dd if=/dev/zero of=/dev/null& pid=$!
         $ kill -USR1 $pid; sleep 1; kill $pid

pid=$!の意味?

これはddのPIDを取得する変数の割り当てですか?そして、最終的に$pid変数で使用されますか?

また、なぜsleepkillを使用するのですか?

これは-USR1を使用する方法ですか?

3
Aby W

dd if=/dev/zero of=/dev/null&

末尾の&は、バックグラウンドでprefixコマンドを実行することを意味します。 (免責事項:これは過度に単純化されたステートメントです)

this を参照してください:

$!最新のバックグラウンドコマンドのPIDです。

したがって、pid=$!は、最新のバックグラウンドPIDを変数pidに割り当てます。これは、dd PIDです。

また、なぜ彼らは睡眠と殺害を使うのですか?.

テストの終了後にddプロセスを終了するには、kill $pidを指定する必要があります(パラメーターが指定されていない場合、killのデフォルトのシグナルはTERMです)、それ以外の場合はddプロセスはバックグラウンドにとどまり、CPUリソースを使い果たす可能性があります。お使いのプラットフォームのシステムモニターを確認してください。

Kill -USR1 $pidはI/O統計を出力しますが、プロセスを終了しません。

1秒のスリープがないと、統計情報出力を端末に書き込む前に、ddプロセスが最後のコマンドステートメントkill $pid **によって終了する場合があります。プロセスは同期していますが、trap + write操作kill -USR1 $pid)は、terminate operationkill $pid)。したがって、sleep 1は、kill $pidの起動を遅らせて、統計出力が確実に印刷されるようにします。

これは-USR1を使用する方法ですか?

ただman dd

実行中の「dd」プロセスにUSR1シグナルを送信すると、I/O統計が標準エラーに出力され、コピーが再開されます。

そしてman 7 signal

   SIGUSR1   30,10,16    Term    User-defined signal 1
   SIGUSR2   31,12,17    Term    User-defined signal 2

両方のステートメントを組み合わせると、USR1がユーザー定義のシグナルであり、ユーザーがそれを中断する方法を提供するddによって定義され、I/O統計情報を印刷します。これはプログラム固有のハンドラーであり、kill -USR1 other_program_pidを使用して統計情報の出力を期待できるという意味ではありません。

また、あなたは興味があるかもしれません これ:なぜSIGUSR1はプロセスを終了させるのですか?

5
林果皞

これは、ddでのUSR1信号の使用法を示すデモにすぎません。

dd if=/dev/zero of=/dev/null &

ddをバックグラウンドで開始し、/dev/zero(プログラムが読み取ると常にゼロが生成されます)から/dev/null(書き込まれたものをすべて破棄する)にデータをコピーします。これは、実験に使用できるddの無害なインスタンスを提供します—ストレージを使い果たすことはなく、必要なだけ実行し続けるため、ユーザーに信号を送信する時間を与えますそれに。

pid=$!

最後のバックグラウンドコマンド($!)のプロセス識別子を変数pidに格納します。

kill -USR1 $pid

USR1シグナルを、識別子がpid変数(この場合はバックグラウンドdd)に格納されている値であるプロセスに送信します。 ddがこの信号を受信すると、現在の進行状況(読み書きされたデータの量)を出力し、コピーを続行します。

sleep 1

1秒待ちます。

kill $pid

TERM信号をddに送信し、ddを終了します。 (ここでバックグラウンドddを実行したままにしても意味がありません。)

上記の2行目の代わりにこれを実行する方がより有益です。

kill -USR1 $pid; sleep 1; kill -USR1 $pid; kill $pid

これにより、ddの進行状況を示すために、1秒間隔で2回進行状況が出力されます。次に、待機せずにddを殺します。

実際の使用では、元のddコマンドの適切な入力と出力、およびおそらく他のいくつかのオプションも指定します。最後のkillは実行しません。 dd独自の合意を完了するために。

最後の質問に答えるために、これはシェル(またはその他の信号)からUSR1信号を送信する方法です。送信する信号で kill を使用し、シグナルを送信するプロセスのプロセス識別子(またはジョブ識別子)。使用できる他の(POSIX以外の)コマンドは、プロセスを名前で検索する場合に pkill および killall です。

6
Stephen Kitt

ほとんどまたはすべてのシェルの場合、$!は、シェルが分岐した最後のプロセスのプロセスID(PIDとも呼ばれる)です。 ddコマンドは&でフォークされたため、ddをフォークした直後のpid=$!ddプロセスIDをシェル変数pidに割り当てます。

プロセスIDは、LinuxまたはUnixがアドレススペースを参照するために使用する番号で、コード内で実行されているコードがあります。

killプログラムの目的はプロセスにシグナル(小さな非同期メッセージ)を送信することであるため、わかりにくい名前があります。信号はほんのわずかで、合計で128です。それらには、番号と名前の両方があります。たとえば、「キル」信号は9番です。 USR1は番号10として定義されています。したがって、kill -USR1 $pid$pidと番号が付けられたプロセスにシグナル10を送信します。 ddの実行には時間がかかる場合があるため、これはほぼ確実に、以前に分岐されてバックグラウンドで実行されたddコマンドのプロセスIDです。 kill $pidコマンドは、TERMシグナルを同じプロセスIDに送信します。 TERMは「終了」を意味します。適切に作成されたプログラムは通常TERMをキャッチし、割り当てたリソースをクリーンアップして終了します。

ddをバックグラウンドで実行してUSR1シグナルを送信し、1秒待ってからddがすべてのリソースの割り当てを解除して終了する理由は完全にはわかりません。コード全体では、ddが長時間実行されると想定しているようですが、そうではない場合があります。このコードには競合状態があり、必要なセマンティクスが何であれ、実際にはそれらを取得できない場合があると思います。

2
Bruce Ediger