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

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

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

実行中の「dd」プロセスにUSR1シグナルを送信し、I / O統計を標準エラーとして印刷してからレプリケーションを再開します。

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

どういう意味ですかpid=$!

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

また、なぜ使用するsleepのですkillか?

使用方法は-USR1

答え1

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

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

引用するこれ:

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

だからpid=$!割り当て最新の背景PIDPIDは変数pidにdd

そしてなぜ彼らは眠りに落ちて殺すのですか?

あなたはする必要がありますkill $pid (パラメータが指定されていない場合、killのデフォルト信号はTERMであり、これはプロセスが終了することを意味します。)ddテストが完了したら、プロセスを終了します。そうしないと、ddプロセスはバックグラウンドに残り、CPUリソースを消費する可能性があります。プラットフォームのシステムモニターを確認して確認してください。

I / O統計は印刷されますが、Kill -USR1 $pidプロセスは終了しません。

dd1秒待機しないと、プロセスが端末に統計出力を書き込む前に、最後のステートメントによってプロセスが終了する可能性があります。kill $pidこれらのプロセスは同期されますが、トラップ+書き込み操作( kill -USR1 $pid) は次より遅くなることがあります。ジョブ終了kill $pid)。したがって、2番目は、統計出力の印刷が完了したことを確認するために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

これら2つの文を組み合わせると、USR1が次のようになることを理解する必要があります。カスタム信号その定義は、ddユーザーにこれを中断する方法を提供することです。I/O 統計の印刷飛行中。これはプログラム固有のハンドラであり、kill -USR1 other_program_pid統計出力を期待できるという意味ではありません。

また、に興味がある可能性があります注:SIGUSR1がプロセスを終了するのはなぜですか?

答え2

USR1これは信号の使用を説明するためのデモですdd

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

ddバックグラウンドで始まると、データは(プログラムが読み取るたびにゼロを生成する)から(書き込まれた内容をすべて削除)/dev/zeroにコピーされます。/dev/nullこれはdd実験に使用できる無害なインスタンスを提供します。これは、ストレージスペースを消費せずに必要なだけ実行できるため、ユーザーが信号を送信する時間を提供します。

pid=$!

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

kill -USR1 $pid

識別子が変数(この場合は背景)USR1に格納されている値であるプロセスにシグナルを送信します。この信号を受信すると、現在の進行状況(読み書きしたデータ量)を印刷してコピーを続けます。piddddd

sleep 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、名前でプロセスを探したいとき。

答え3

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

プロセスIDは、LinuxまたはUnixでいくつかのコードが実行されるアドレス空間を参照するために使用される番号です。

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

ddなぜバックグラウンドで実行し、USR1信号を送信して1秒待ってから、すべてのddリソースを解放して終了するのかわかりません。完全なコードスニペットでは、dd実行するのに長い時間がかかると仮定しているようですが、そうではありません。私の考えでは、このコードには競争条件があり、あなたが望む意味が何であれ実際には得られないかもしれません。

答え4

ddコマンドをフォアグラウンドで実行し、現在の進行状況を表示したい場合。status=progressフラグを使用してコマンドを実行してみてください。

sudo dd if=/dev/sda of=/dev/sdb status=progress

これにより、進行状況が動的に表示されます。

これは、12.0(2018)以降のFreeBSDでの実装にも使用できるGNU実装dd(2015年にリリースされたバージョン8.24に追加)への拡張ですが、通常、他のBSDでの他の実装は除外されます。dd

関連情報