$ 睡眠 100 &[1] 9298
使用
ピドフ指定したプログラム名のプロセス ID を表示できます。
$ pidof sleep9298
$ cat /proc/9298/maps08048000-0804b000 r-xp 00000000 08:01 977399 /bin/sleep0804b000-0804c000 rw -p 00003000 08:01 977399 /bin/sleep0804c000-0806d000 rw-p 0804c000 00:00 0 [ヒープ]b7c8b000-b7cca000 r--p 00000000 08:01 443354...bfbd8000-bfbed000 rw-p bfbd8000 00:00 0 [スタック]ffffe000-fffff000 r-xp 00000000 00:00 0 [vdso]
プログラムは実行後、メモリにロードされてプロセスになります。上記は、プログラム命令、データ、およびプログラムのコマンド ライン パラメーターと環境変数を保存するために使用される一部のスタック スペースを含むプロセスのメモリ イメージ (仮想メモリ) を示しています。動的メモリ アプリケーションに使用されるヒープ スペースも割り当てられています。
コマンドラインでのプログラム実行処理の詳細については、「Linuxコマンドラインでのプログラム実行の瞬間」を参照してください。
実際、プロセスを作成する、つまりプログラムを実行する方法は他にもあります。たとえば、いくつかの設定を使用すると、システムの起動時にプログラムを自動的に開始できます (詳細については、を参照してください)。
男の初期化)、または設定によって
クロン(または
で) プログラムを定期的に開始できるようにします。また、シェルスクリプトを記述し、スクリプトファイルを実行すると、そのファイル内のプログラムが実行されプロセスとなる方法もあります。これらのメソッドの詳細は紹介しません。プロセスのプロパティを表示する方法を学びましょう。
追加する必要があることが 1 つあります。コマンド ラインでプログラムを実行するには、次のように渡すことができます。
ウリミット組み込みコマンドは、プロセスが開くことができるファイル記述子の最大数、最大スタック領域、仮想メモリ領域など、プロセスが利用できるリソースを設定するために使用されます。具体的な使用方法については、を参照してください。
ヘルプリミット。
通過できる
PSこのコマンドを使用して、プロセス関連の属性とステータスを表示します。この情報には、プロセスが属するユーザー、プロセスに対応するプログラム、および
CPUメモリ使用量やその他の情報。それらの表示方法を理解しておくと、関連する統計分析やその他の操作に役立ちます。
システム内のすべての現在のプロセスのプロパティを表示します。
$ ps -ef
コマンド内に特定の文字を含むプログラムに対応するプロセスを表示、プロセス
IDは1です。
TTYのために?端末に関係がないことを示します。
$ ps -C init PID TTY TIME CMD 1 00:00:01 init ?
特定のユーザーによって開始されたプロセスを選択します。
$ ps -U ハヤブサ
指定した内容を指定した形式で出力します。 以下のようにコマンド名と出力します。
CPU使用率:
$ ps -e -o %C %c
印刷する
CPU最もよく使用されているプログラムのトップ 4:
$ ps -e -o %C %c | ソート -u -k1 -r ヘッド -5 7.5 Firefox-bin 1.1 Xorg 0.8 scim-panel-gtk 0.2
最大の仮想メモリを使用している 5 つのプロセスを取得します。
$ ps -e -o %z %c | ソート -n -k1 -r ヘッド -5349588 firefox-bin 96612 xfce4-terminal 88840 xfdesktop 76332 gedit 58920 scim-panel-gtk
システム内のすべてのプロセス間には「親族関係」があります。
pstreeこの関係を確認してください:
$ pstree
システム プロセスの呼び出しツリーが上に表示され、現在のシステム内のすべてのアクティブなプロセス間の呼び出し関係が明確にわかります。
$トップ
このコマンドの最大の特徴は、プロセス情報を動的に表示できることです。もちろん、次のような他のパラメーターも提供します。
-S累積実行時間に従って並べ替えて表示することも、次のように使用することもできます。
-u指定したユーザーが開始したプロセスなどを表示します。
補充:
トップこのコマンドは対話型をサポートします。たとえば、
あなたこのコマンドはユーザーのすべてのプロセスを表示し、パスの受け渡しをサポートします。
k使用している場合はプロセスを強制終了するコマンド。
-n 1バッチ処理モードを有効にするオプションの場合、具体的な使用方法は次のとおりです。
$ トップ -n 1 -b
興味深い問題について説明しましょう。それは、同時に 1 つのプログラムだけを実行する方法です。
これは、プログラムの実行中は再度開始できないことを意味します。それで、どうすればいいでしょうか?
同じプログラムが多数のコピーにコピーされ、異なるファイル名が付けられ、異なる場所に配置される場合、状況はさらに悪化します。そのため、最も単純なケースを考えてみましょう。つまり、このプログラムはシステム全体で一意であり、名前も一意です。 。この場合、上記の質問に答えるにはどのような方法がありますか?
一般的なメカニズムは、プログラムが実行されているかどうかをプログラムの先頭で確認し、実行されている場合は停止し、実行されていない場合は後続のコードの実行を継続します。
前の仮定ではプログラム ファイル名とコードの一意性が確保されているため、戦略は多様です。
PSこのコマンドは、現在のすべてのプロセスに対応するプログラム名を検索し、それ自体のプログラム名と 1 つずつ比較します。それがすでに存在する場合、それはすでに実行されていることを意味します。
ps -e -o %c | grep -q ^init$ #現在のプログラムが実行されているかどうかを確認します [ $? -eq 0 ] && exit #実行されている場合、$?正常に実行されました
実行するたびに、まず、指定された場所に自分自身を保存するプロセスがあるかどうかを確認します。
IDファイルが存在しない場合は実行を続行し、存在する場合はプロセスを表示します
ID実行されている場合は終了し、そうでない場合は新しいプロセスをファイルに書き換えます。
ID、続けます。
pidfile=/tmp/$0.pidif [ -f $pidfile ]; then OLDPID=$(cat $pidfile) ps -e -o %p -d grep -q ^$OLDPID$ | && exitfiecho $$ > $pidfile#... コード本体# シグナル 0 のアクションを設定します。プログラムが終了すると、シグナルがトリガーされて一時ファイル トラップが削除されます rm $pidfile 0
さらに多くの実装戦略をご自身で自由に使用してください。
各プロセスがスムーズに実行されることを保証することに加えて、特定のタスクが最初に完了できるようにするために、システムはプロセスをスケジュールするときに、優先度に応じてタイム スライスをローテーションする一般的なスケジューリング アルゴリズムなど、特定のスケジューリング方法を使用します。この場合、パスすることができます
レニス実行中のプログラムの優先順位を調整します。例: `
$ ps -e -o %p %c %n | grep xfs 5089 xfs 0
$ renice 1 -p 5089renice: 5089: setpriority: 操作は許可されていません$ sudo renice 1 -p 5089 #権限が必要です [sudo] falcon のパスワード:5089: 古い優先度 0、新しい優先度 1$ ps -e -o %p % c %n grep xfs #もう一度見てみると、優先度が調整されています 5089 xfs 1
コマンドラインからプログラムの実行やプロセスの作成ができるので、終了する方法もあります。通過できる
殺すもちろん、このコマンドはユーザーが開始したプロセスにシグナルを送信してプロセスを終了します。
根ほとんど
殺すすべてのプロセス (除く)
初期化外)。例えば、
$ sleep 50 & #プロセスの開始 [1] 11347$ kill 11347
殺すこのコマンドはデフォルトで終了シグナルを送信します (
シグターム) をプログラムに追加し、プログラムを終了させますが、
殺す他の信号も送信でき、これらは次のように定義できます。
マン7シグナルからもご覧いただけます
殺す -lそれをリストアップしてください。
$ man 7 signal$ kill -l 1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL 5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE 9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR213) SIGPIPE 14) SIGALRM 15 ) シグターム16) SIGSTKFLT17) SIGCHLD 18) SIGCONT 19) SIGSTOP 20) SIGTSTP21) SIGTTIN 22) SIGTTOU 23) SIGURG 24) SIGXCPU25) SIGXFSZ 26) SIGVTALRM 27) SIGPROF 28) SIGWINCH29) SIGIO 30) SIGPWR 31) SIGSYS 34) SIGRTMIN35) SIGRTMIN+1 36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+439) SIGRTMIN+5 40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+843) SIGRTMIN+9 44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+1247) SIGRTMIN+13 48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-1451) SIGRTMAX-13 52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-1055) SIGRTMAX-9 56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-659) SIGRTMAX-5 60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-263) SIGRTMAX-1 64) SIGRTMAX
たとえば、次のように使用します。
殺す送信するコマンド
シグストッププログラムに一時停止してから送信するよう信号を送る
シグコント信号はそれを動かし続けます。
$ sleep 50 &[1] 11441$ jobs[1]+ 実行中の sleep 50 &$ kill -s SIGSTOP 11441 #これは、フォアグラウンド プロセスで CTRL+Z 操作を実行するのと同じです $ jobs[1]+ 停止した sleep 50$ kill - s SIGCONT 11441 #これは、バックグラウンド プロセスを実行するために使用した前の bg %1 操作と同等です $ jobs[1]+ 実行中の sleep 50 &$ kill %1 #現在のセッションでは、ジョブ番号を通じてプロセスを制御することもできます $ jobs[1]+ Terminated sleep 50
見える
殺すこのコマンドは非常に優れた機能を提供しますが、それはプロセスにのみ基づいています。
IDまたはプロセスを制御するジョブ、
殺すそして
キオールプログラム名やユーザー名によってプロセスを制御する方法を拡張する、より多くのオプションが提供されています。詳しい使用方法については、マニュアルを参照してください。
プログラムが終了するとき、プログラムが正常終了したか異常終了したかを判断するにはどうすればよいですか? Linux でのあの古典をまだ覚えていますか?
こんにちは世界プログラム?コードの最後には必ず行があります
0を返す声明。これ
0を返す実際、プログラマはプロセスが正常に終了したかどうかを確認できます。プロセスが異なる値を返した場合、プロセスはまだ実行されていないため、異常終了したと言えます。
0を返すこのステートメントは終了します。
では、プロセスの終了ステータス、つまり戻り値を確認するにはどうすればよいでしょうか?
存在する
シェル、この特別な変数を確認できます
$?、前のコマンドが実行された後の終了ステータスが保存されます。
$ test1bash: test1: コマンドが見つかりません$ echo $?127$ cat ./test.c | grep hello$ echo $?1$ cat ./test.c | grep hi printf(こんにちは、私!n);$ echo $?0
0を返すのが暗黙のルールになっているようですが、明確に規定した規格はありませんが、プログラムが正常に復帰する場合は必ず0を返すことができます。
$?では0を検出しますが、異常時は常に0以外の値を検出します。これは、プログラムの最後に次の手順に従うのが最善であることを示しています。
0番出口誰でも試験に合格できるように
$?プログラムが正常に終了するかどうかを確認します。ある日、誰かがあなたのプログラムを時々使用し、その終了ステータスを確認しようとしたときに、あなたが不可解なエラーを返したとします。
-1または 1、その場合、彼は非常に悩み、自分が書いたプログラムのどこに問題があるのか疑問に思うでしょう。彼はそれを長い間チェックしますが、彼はあなたを非常に信頼しているので、あなたのプログラミングの習慣を疑うことはありません。最初から最後まで違うでしょう!
設計と実装を容易にするために、通常、大きなタスクは小さなモジュールに分割されます。さまざまなモジュールは、開始後にプロセスになります。どのように相互に通信してデータを交換し、連携するのでしょうか。 『UNIX 環境における上級プログラミング』では、パイプ (名前なしパイプと名前付きパイプ)、シグナル (
信号)、 メッセージ (
メッセージ) キュー (メッセージキュー)、共有メモリ (
mmap/ムンマップ)、セマフォ(
セマフォ、主にプロセス間、プロセスの異なるスレッド間の同期に使用されます)、ソケット (
ソケット、異なるマシン間のプロセス通信をサポートします)など、シェルでは通常、パイプとシグナルが直接使用されます。以下では主に、シェル プログラミングにおけるパイプとシグナル メカニズムのいくつかの使用法を紹介します。
Linux では、次のように渡すことができます。
|2 つのプログラムを接続すると、後のプログラムの入力を前のプログラムの出力に接続できるため、パイプと呼ばれています。 C 言語では、名前のないパイプを作成するのが非常に簡単で便利です。
パイプ関数、2 つの要素を渡す
整数型の配列で十分です。この配列には実際には 2 つのファイル記述子が格納されており、親プロセスが最初のファイル記述子に何かを書き込んだ後、子プロセスは最初のファイル記述子からそれを読み取ることができます。
使用するコマンドラインが多すぎる場合、このパイプは
|頻繁に使用する必要があります。たとえば、上記のデモがあります
PSコマンドの出力は次のようになります
grepコマンド入力:
$ ps -ef 初期化 |
この「パイプ」は実際に 2 つのプログラムの入力と出力をリンクできるという非常に魔法のようなものだと思うかもしれませんが、それらはどのように実装されているのでしょうか。実際、そのような一連のコマンドが入力されると、現在のシェルは適切な解析を実行し、前のプロセスの出力をパイプの出力ファイル記述子に関連付け、後続のプロセスの入力をパイプの入力ファイル記述子に関連付けます。この関連付けプロセスは、入力と出力を通じて機能します。
ダップ(または
fcntl)を達成します。
名前付きパイプは実際にはファイルです (名前のないパイプもファイルに似ています。これは 2 つのファイル記述子に関連していますが、一方の側でのみ読み取り、もう一方の側で書き込むことができます)。操作中に先入れ先出しを満たす必要があり、コンテンツを持たない名前付きパイプから読み取ろうとした場合も同様に、現在実行中のプログラムが名前付きパイプに書き込もうとした場合はブロックされます。それを読むとブロックされます。以下の効果を参照してください。
$ mkfifo fifo_test #mkfifo コマンドを使用して有名なパイプを作成します $ echo fefe > fifo_test #コンテンツを fifo_test ファイルに書き込もうとしましたが、ブロックされました。次の操作を続行するには別の端末を開く必要があります $ cat fifo_test #別の端末を開きます。 、覚えておいてください、別のものを開いてください。 fifo_test fefefeの内容を読み出してみる
こちらです
エコーそして
猫2 つの異なるプログラムです。この場合、
エコーそして
猫開始された 2 つのプロセスの間には親子関係はありません。ただし、名前付きパイプを介して通信することはできます。
このような通信方法は、特定の状況に非常に適しています。たとえば、このアーキテクチャは 2 つのアプリケーションで構成され、そのうちの 1 つはループを介して継続的に読み取ります。
fifo_test次に何をすべきかを決定するためにコンテンツを作成します。このパイプにコンテンツがない場合、無限ループによりリソースを消費せずにブロックされ、もう一方のパイプは制御プログラムとして流れ続けます。
fifo_test前のプログラムに何をすべきかを指示するために、それにいくつかの制御情報を書き込みます。以下に非常に簡単な例を書きます。いくつかの制御コードを設計すると、制御プログラムは引き続き実行されます。
fifo_testこれを書き込むと、アプリケーションはこれらの制御コードに基づいてさまざまなアクションを実行します。もちろん、に行くこともできます
fifo_test制御コード以外の他のデータを渡します。
アプリケーションコード
$ cat app.sh #!/bin/bash FIFO=fifo_test while :; do CI=`cat $FIFO` #CI --> 制御情報 case $CI in 0) echo 制御番号はゼロです、何かをしてください... ;; 1) echo CONTROL 番号は 1 です、何かをしてください... ;; *) echo CONTROL 番号は認識されません、何か他のことをしてください... ;;
制御プログラムコード
$ cat control.sh #!/bin/bash FIFO=fifo_test CI=$1 [ -z $CI ] && コントロール情報を空にすることはできません && exit echo $CI > $FIFO
あるプログラムがパイプを通じて別のプログラムの動作を制御する
$ chmod +x app.sh control.sh #これら 2 つのプログラムの実行権限を変更して、ユーザーが実行できるようにします $ ./app.sh #ターミナルでこのアプリケーションを起動し、./control.sh を通じて制御を送信します 出力を確認しますコードの後に CONTROL 番号が 1 であるため、別のことを行ってください... #1 を送信した後、CONTROL 番号が 0 であるため、別のことを行ってください... #0 を送信した後、CONTROL 番号が認識されないため、別のことを行ってください... #制御コードの後に不明なコードを送信 $ ./control.sh 1 #別の端末で、アプリケーションの動作を制御するための制御情報を送信 $ ./control.sh 0 $ ./control.sh 4343
このようなアプリケーション アーキテクチャは、ローカル マルチプログラム タスクの設計に非常に適しています。
ウェブCGI、その後、リモコンの要件にも適合します。導入
ウェブCGI唯一の変更点は、制御プログラムです。
./control.sh入れます
ウェブの
CGIディレクトリに移動し、それに準拠するようにいくつかの変更を加えます。
CGIドキュメントの出力形式の表現を含む仕様 (ファイルの先頭に出力する必要がある)
content-tpye: テキスト/htmlおよび空行)と入力パラメータの取得
(ウェブ入力パラメータは次の場所に保存されます。
QUERY_STRING環境変数)。非常にシンプルな
CGI制御プログラムは次のように記述できます。
#!/bin/bashFIFO=./fifo_testCI=$QUERY_STRING[ -z $CI ] && コントロール情報を空にすることはできません && exitecho -e content-type: text/htmlnnecho $CI > $FIFO
実際にご使用の際は必ずご確認ください
コントロール.shアクセスできる
fifo_testパイプを持ち、ブラウザ経由で制御するための書き込み権限を持っています。
app.sh:
http://ipaddress_or_dns/cgi-bin/control.sh?0
疑問符
?以下の内容は、
QUERY_STRING、前と同様に
1ドル。
このような応用は、遠隔制御、特に組み込みシステムの遠隔制御にとって、実用上非常に重要である。昨年の夏期講習では、このようにしてモーターの遠隔制御を実施しました。まず、速度や方向などの制御を含むモーターの回転を制御するための簡単なアプリケーションが実装されます。遠隔制御を実現するために、モーターの回転に関連するさまざまなプロパティを制御するいくつかの制御コードを設計しました。
C 言語では、名前付きパイプを使用する場合、データの読み取りと書き込みの際にシェルと似ています。
読む、
書く電話、作成
FIFOときに使用されます
mkfifo関数呼び出し。
シグナルは、Linux ユーザーがアクセスできるソフトウェア割り込みです。
殺すコマンドは特定のシグナルをプロセスに送信します。または、次のような一部のシグナルをキーボード経由で送信できます。
CTRL+Cトリガーとなる可能性があります
SGIINT信号を送りながら
CTRL+トリガーとなる可能性があります
シギットシグナルなど さらに、カーネルは、境界外のメモリにアクセスするときなど、特定の状況下でもプロセスにシグナルを送信します。
SGISEGVシグナルはもちろん、プロセス自体も通過できます
殺す、
上げる関数がそれ自体にシグナルを送信するまで待ちます。 Linux でサポートされている信号タイプについては、次のように渡すことができます。
マン7シグナルまたは
殺す -l関連リストと手順を参照してください。
一部の信号では、プロセスはデフォルトの応答アクションを持ちますが、一部の信号では、プロセスはそれらを単に無視することもあります。もちろん、ユーザーは特定の信号に対して特別な処理関数を設定することもできます。シェルでは、次のように渡すことができます
トラップコマンド (シェル組み込みコマンド) を使用して、信号 (コマンドまたは定義された関数) に応答してアクションを設定します。C 言語では、次のように使用できます。
信号シグナルに登録されたハンドラー関数を呼び出します。これは単なるデモンストレーションです
トラップコマンドの使用法。
$ function signal_handler { echo hello, world.; } #signal_handler 関数を定義します $trap signal_handler SIGINT #このコマンド設定を実行します: SIGINT シグナルを受信したときに hello, world を出力します $ hello, world #CTRL+C を押して画面を表示します The helloそしてワールド文字列が出力されます
同様に、信号 0 の応答アクションを設定すると、
トラップC言語プログラムをシミュレートするには
出口プログラム終了機能の登録、つまり
トラップ signal_handler SIGQUITセット
シグナルハンドラーこの関数はプログラムの終了時に実行されます。信号 0 は特殊な信号です。
POSIX.1信号番号 0 はヌル信号として定義されており、特定のプロセスがまだ存在するかどうかを判断するためによく使用されます。この信号は、プログラムが終了するとトリガーされます。
$ cat sigexit.sh#!/bin/bashfunction signal_handler { echo hello, world}trap signal_handler 0$ chmod +x sigexit.sh$ ./sigexit.sh #実際のシェル プログラミングでは、プログラムの終了時にこのメソッドを使用してクリーンアップが行われます。一時ファイルの作業を終了しています hello, world
複数のコマンドを渡すとき
|,>,<, ;, (,)この一連のコマンドを組み合わせると、通常、パイプなどを介して通信する複数のプロセスが開始されます。タスクを実行するときに、処理する必要のある他のタスクがある場合があるため、コマンド シーケンスの最後に & を追加するか、コマンドの実行後に を押すことがよくあります。
CTRL+Z前のコマンドを一時停止します。他のタスクを実行するため。他のいくつかのタスクを完了した後、パスします
フロムこのコマンドは、バックグラウンド タスクをフォアグラウンドに切り替えます。このような制御プロセスは通常、ジョブ制御と呼ばれ、これらのコマンド シーケンスはジョブと呼ばれます。このジョブには 1 つ以上のプログラム、1 つ以上のプロセスが含まれる場合があります。以下に、一般的に使用されるいくつかのジョブ制御操作を示します。
$ 睡眠 50 &[1] 11137
シェル組み込みコマンドを使用する
フロムジョブ 1 を最前面に移動して、 を押します。
CTRL+Zプロセスを一時停止する
$ fg %1sleep 50^Z[1]+ スリープを停止しました 50
$ jobs # 現在のジョブのステータスを確認します。1 つのジョブは停止しています [1] + 停止した sleep 50$ sleep 100 & # 別のジョブをバックグラウンドで実行します [2] 11138$ jobs # 現在のジョブのステータスを確認します。1 つは実行中、もう 1 つは実行中です。停止中 [ 1] + 停止中のスリープ 50[2] - 実行中のスリープ 100 &
$ bg %1[2]+ スリープ 50 &
ただし、コマンドラインでジョブ制御を使用するには、現在のシェル、カーネル端末ドライバーなどがジョブ制御をサポートしている必要があります。
「UNIX環境における高度なプログラミング」