
私はプログラムのマニュアルページを理解しようとしています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 はdd
PID です。
また、なぜスリープとキルを使用するのでしょうか?
必要なのはkill $pid
(パラメータが指定されていない場合、kill のデフォルト シグナルはプロセス終了の TERM になります)dd
テストが完了したらプロセスを終了してください。そうしないとdd
、プロセスがバックグラウンドに留まり、CPU リソースを使い果たしてしまう可能性があります。プラットフォームのシステム モニターで確認してください。
I/O 統計を印刷しますがKill -USR1 $pid
、プロセスは終了しません。
1秒のスリープがなければ、統計出力を端末に書き込む前に、dd
最後のコマンドステートメント**によってプロセスが終了する可能性があります。プロセスは同期的ですが、kill $pid
トラップ+書き込み操作(kill -USR1 $pid
)はより遅いかもしれない操作を終了する(kill $pid
)。したがって、統計出力が印刷されたことを確認するために、sleep 1
2 番目の起動を遅らせます。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
バックグラウンド)にシグナルを送信します。このシグナルを受信すると、現在の進行状況 (読み書きされたデータの量) を出力し、コピーを続行します。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
プロセスを名前で検索する場合。
答え3
ほとんどまたはすべてのシェルでは、$!
はシェルがフォークした最後のプロセスのプロセス ID (PID とも呼ばれる) です。 コマンドdd
は でフォークされた&
ため、pid=$!
フォーク直後はプロセス ID をシェル変数 にdd
割り当てます。dd
pid
プロセス ID は、Linux または Unix が、コードが実行されているアドレス空間を参照するために使用する番号です。
このkill
プログラムの名前は直感的ではありません。これは、その目的がプロセスにシグナル (小さな非同期メッセージ) を送信することにあるためです。シグナルはわずか数個 (合計で 128 個程度) で、番号と名前の両方があります。たとえば、「kill」シグナルは番号 9 です。USR1 は番号 10 として定義されています。したがって、はkill -USR1 $pid
番号 10 のプロセスにシグナル 10 を送信します$pid
。dd
実行に時間がかかることがあるため、これはほぼ間違いなく、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 で追加)、dd
FreeBSD 12.0 (2018) 以降の実装でも利用可能ですが、他の BSD を含む他の実装では通常利用できません。