あらゆるプログラム(例: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&

末尾は、&プレフィックス コマンドをバックグラウンドで実行することを意味します。(免責事項: これは単純化しすぎた記述です)

参照するこれ:

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

だからpid=$!割り当てる最新の背景PID変数 pid はddPID です。

また、なぜスリープとキルを使用するのでしょうか?

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

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

1秒のスリープがなければ、統計出力を端末に書き込む前に、dd最後のコマンドステートメント**によってプロセスが終了する可能性があります。プロセスは同期的ですが、kill $pidトラップ+書き込み操作kill -USR1 $pid)はより遅いかもしれない操作を終了するkill $pid)。したがって、統計出力が印刷されたことを確認するために、sleep 12 番目の起動を遅らせます。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統計出力を期待できるという意味ではありません。

また、次の点にも興味があるかもしれませんthis: SIGUSR1 によってプロセスが終了するのはなぜですか?

答え2

USR1これは、 を使用した信号の使用方法を説明するための単なるデモンストレーションですdd

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

ddバックグラウンドで起動し、データを/dev/zero(プログラムが読み取るたびにゼロを生成)から/dev/null(書き込まれたものはすべて破棄) にコピーします。これによりdd、実験に使用できる無害なインスタンスが提供されます。ストレージを消費せず、必要なだけ実行し続けるため、ユーザーはシグナルを送信する時間があります。

pid=$!

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

kill -USR1 $pid

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

sleep 1

1秒待ちます。

kill $pid

TERMは にシグナルを送信しddddを終了します。(ここでバックグラウンドを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は でフォークされた&ため、pid=$!フォーク直後はプロセス ID をシェル変数 にdd割り当てます。ddpid

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

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

なぜバックグラウンドで実行しdd、USR1 シグナルを送信し、1 秒待ってからddすべてのリソースの割り当てを解除し、終了するのか、よくわかりません。コード フラグメント全体では、長時間実行されることを想定しているようですがdd、これは正しくない可能性があります。このコードには競合状態があり、望ましいセマンティクスが何であれ、実際には競合状態にならない可能性があります。

答え4

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

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

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

これは GNU 実装の拡張でありdd(2015 年にリリースされたバージョン 8.24 で追加)、ddFreeBSD 12.0 (2018) 以降の実装でも利用可能ですが、他の BSD を含む他の実装では通常利用できません。

関連情報