気になったのですが、任意の処理を一定時間凍結する方法はないのでしょうか?
私が言いたいのは、あるアプリケーション(おそらくrootとして実行されている)が、既に実行されている別のプロセス(GUIとコマンドラインの両方のプロセス)の実行を一時停止して、後で再開することは可能でしょうか?言い換えれば、私は特定のプロセスを一定時間、linuxのスケジューラによってスケジュールされたくないのです
55 Pal Szasz 2012-10-10
こちらをご覧ください
プロセスの実行を一時停止できるシグナルは2つあります。1つは “優美 “であり、もう1つは “強制 “です
優雅な “ものはSIGTSTP
で、その目的は、プロセスがその気になれば、SIGCONT
を受け取るまで実行を中断してくださいと “親切に “お願いすることです。SIGTSTP
の場合、プロセスはSIGTSTPを無視して実行を続けることができるので、SIGTSTPを扱うように設計されたプログラムの協力が必要です
強制的な」ものは SIGSTOP
であり、その目的はそのプロセスに関連付けられたすべてのユーザ空間スレッドをサスペンドすることです。プロセスが SIGSTOP
を無視することは SIGKILL
を無視することと同じくらい不可能です (後者は強制的にプロセスを終了させます)
ここで述べたものを含め、任意のシグナルを送信するには、kill
, killall
, pkill
のようなプログラムを使うか、システムコール kill(2)
を使うことができます。上記のいずれについても、プラットフォーム/アーキテクチャ/バージョンに依存する詳細や正誤表については、お使いのオペレーティングシステムのマニュアルを参照してください。これらのコマンドや syscall の中の “kill” という単語は間違った呼び方をしていることに注意してください。これらのコマンドはプロセスを終了させるためだけに設計されているわけではありません。シグナルのうちの特定のものを送信することでそれを行うことができますが、シグナルはプロセスの終了以外の機能にも使用できます。例えば、SIGSTOP
はプロセスを一時停止するだけであり、このように送信できるシグナルはいくつかありますが、そのうちの一つに過ぎません
一定時間が経過した後に自動的にプロセスを再開する条件を追加するには、監視プロセスを起動させるためにタイマーを設定して実行中のままの監視プロセスを使用する必要があり、監視プロセスは再び kill(2)
を呼び出して停止しているプロセスに SIGCONT
シグナルを送り、カーネルに実行の再開を要求します。さらに、システムが非常に忙しい場合、監視プロセスはタイマーの期限が切れるまで起こされないかもしれないので、ウェイクアップが遅れるかもしれません
サスペンドされたプロセスのサスペンドと再開の非常に正確な精度に依存している場合、リアルタイム権限でモニタリングプログラムを実行する必要があるかもしれません (プロセスのリアルタイム化についての情報は この manpage の sched_setscheduler(2)
を参照してください)。また、リアルタイムスケジューリングと組み合わせて、Linux カーネルの機能である高分解能タイマを使用することもできます (ハードウェアがサポートしている場合にのみ利用可能です)
これを実装するためにどのような技術を使用するかを示していませんでした。最低限、少なくともbashスクリプトが必要になるでしょう。以下は、あなたのクエリの概念を証明するためのbashの “スクリプト “です(未検証なので注意してください)。正確なタイミングが必要な場合は、C/C++や他のネイティブ言語でプログラムを書いて、リアルタイムスケジューリングやhrtimersを使う必要があります
#!/bin/bash
#This is the process you want to suspend.
screen -mdS child bash -c "cat /dev/urandom | base64"
#This is the process ID of the child process
THEPID=$(screen -list | grep child | cut -f1 -d'.' | sed 's/\W//g')
#Send SIGSTOP to the child process.
kill -SIGSTOP ${THEPID}
#Now it is suspended. This process will sleep for 10 seconds asynchronously, then resume the process.
screen -mdS monitor bash -c "sleep 10; kill -SIGCONT ${THEPID}"
スクリプトが終了して制御スクリプトが終了しますが、screen
がモニタープロセスを制御しているため、(sleep
に渡された引数に基づいて)10秒間バックグラウンドで実行し続け、その後、(sleep
に渡された引数に基づいて)起動して子プロセスを継続することに注意してください。しかし、これは制御スクリプトが終了してからずっと後になります。同期的に時間が経過するのを待ちたい場合は、screen
の2回目の呼び出しを省略して、制御スクリプトにスリープとキルをハードコーディングすればいいだけです
実行することで、実際にプロセスがサスペンドされることをテストできます
screen -rS child
このスクリプトを起動した後にコンソールには何も表示されません。タイマーが切れると(10秒)、画面にbase64データ(0~9とA~Fのランダムな文字)が表示されます。Ctrl+Cを押して終了します
83 allquixotic 2012-10-10
はい、STOP信号を送ってプロセスを一時停止させ、CONTを送って続行させることができます
usage:
kill -STOP <pid>
kill -CONT <pid>
15 None 2014-01-15
もし、”freeze” の定義が適当に緩いのであれば、renice
コマンドをチェックしてみてください
Reniceでは、実行中のプロセスのスケジューリングの優先度を変更することができます
通常のプロセスのナイス値は 0 です。 ナイス値を上げると、”why don’t you go first” のように、プロセスをナイスにします。一方、ナイス値を下げると、プロセスはナイスではなくなります。ナイス値の範囲は-20~19です
誰でも自分のプロセスをより良くすることができます。ルートだけがプロセスをより良くしたり、他のユーザーのプロセスをより良く変更することができます
プロセスのナイス値を19に設定すると、システム上で何もしたくないときにのみ実行されます
ここでは、私のローカルのlinuxボックスで実行した例を示します
ps -l
を使用して、NI列を見てプロセスの良い値を確認してください
-> ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD 0 S 29190 402 31146 0 75 0 - 16547 wait pts/0 bash 0 T 29190 1105 402 0 75 0 - 23980 finish pts/0 vim 0 R 29190 794 402 0 76 0 - 15874 - pts/0 ps
vimプロセスでrenice +10
を実行すると、優先度が低くなります
-> renice +10 -p 1105 1105: old priority 0, new priority 10 -> ps -l F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY CMD 0 S 29190 402 31146 0 76 0 - 16547 wait pts/0 bash 0 T 29190 1105 402 0 95 10 - 23980 finish pts/0 vim 0 R 29190 1998 402 0 78 0 - 15874 - pts/0 ps
もし「フリーズ」を「システム上の他の誰にも迷惑をかけない」という意味に拡張できると仮定すると、次のようなスクリプトを作成することができます
renice 20 -p <pid of interest> sleep <certain amount of time> renice 0 -p <pid of interest>
(rootで実行することを忘れずに)
上記のps -l
出力で、興味深い列が小さな青いボックスにきれいに表示されるように、少し自由にしたことに注意してください 🙂
12 Maurice 2012-10-13