ラベル プロセス起動 の投稿を表示しています。 すべての投稿を表示
ラベル プロセス起動 の投稿を表示しています。 すべての投稿を表示

2011年9月23日金曜日

プロセスを起動し結果を文字列として取得 (popen/pclose)

プロセスを起動し結果を文字列として取得する例です。

popen / pclose を利用したプロセスの起動では、"cat makefile | wc" のようなシェル上で利用するパイプによるコマンドを渡すことも可能です。

リダイレクションによる実装例は こちら

実行結果

プロセスを起動し結果を文字列として取得 (fork,pipe,dup,execlp)

プロセスを起動し結果を文字列として取得する例です。

リダイレクションにより子プロセスから出力される文字列を親プロセスへと渡しています。

ping コマンド等、C言語などにて実装が困難な処理を外部コマンドとして呼び出し、その結果にて処理を分岐する用途に使う際に便利になります。

実行結果

2011年9月4日日曜日

TCP/IP を利用したソケット通信によるサーバー/クライアント通信

TCP/IP を利用したソケット通信によるサーバー/クライアント通信例です。

以下の例では、クライアントから送られたメッセージをそのまま送り返す echo 機能を持ったサーバと、そのサーバと通信を行うためのクライアントの実装を行っています。


ソース等をまとめたもの:DL(tcpsvcl.zip)

サーバー クライアント

TCP ライブラリ: tcp_lib.cpp TCP ライブラリ: tcp_lib.h

実行結果(サーバー側) 実行結果(クライアント側)

2011年9月3日土曜日

mypopen 関数の実装 (fork,pipe,dup,execlp)

プロセス間通信、リダイレクション、パイプ処理等により、popen, pclose 関数を実装する例題です。

main 関数内での mypopen, mypclose 関数の利用例はそのまま popen, pclose でも利用可能です。

実行結果

mysystem 関数の実装 (fork,execlp)

system 関数と同等の機能を有する関数 (mysystem) を実装する例題です。

execlp(execvp,..) 関数は引数に実行するコマンドとその引数を指定すると、そのコマンドを実行してくれますが、実行後プログラムを終了してしまいます。
そこで、そのコマンドを実行後も処理を続行したい場合には、fork により子プロセスを作成し、その子プロセス内にて execlp 等を実行しています。
execlp 関数の終了後、子プロセスが終了しても親プロセスで続けて処理を行うことができます。

また、execlp 関数では、通常のシェルで行うようなパイプやリダイレクション処理 ( | < > etc.) や正規表現 (? * etc.) による複雑な処理を行うことができません。
複雑な処理を行う場合にはシェルコマンド (/bin/sh etc.) を介してコマンドを実行します。

ex.

execlp("/bin/sh","/bin/sh","-c","ls | wc > output.txt",NULL);

実行結果

リダイレクション (fork,pipe,dup,execlp) によるプロセスの連結

リダイレクション (fork,pipe,dup,execlp) によりプロセスを連結し、出力する例題です。

例題では、2つのプロセスを起動し、それぞれのプロセスからの入出力をリダイレクトしています。

実行結果

リダイレクション (dup,execlp) により標準入出力の変更

リダイレクションにより標準入出力をファイルとする例題です。

例題では、標準入力を引数1で指定されたファイル、標準出力を引数2で指定されたファイルへ変更し、入力で与えられる文字列の行数を wc コマンドを実行することによりカウントし、出力しています。
結果は引数2のファイルへと保存されます。

実行結果

プロセス間通信 (双方向 (fork,pipe,socketpair)) によるメッセージの送受信

プロセス間通信 (双方向 (fork,pipe,socketpair)) により、親子プロセス間にてメッセージの送受信を行う例です。

双方向の通信を行う例として、pipe() 関数により2本のパイプを準備する方法と、socketpair() 関数により双方向通信が可能なファイル記述子を準備する方法の2通りが考えられます。
以下では、それぞれの方法についての例を示します。

2本のパイプを準備する方法 実行結果

双方向通信が可能なファイル記述子を準備する方法 実行結果

プロセス間通信 (リダイレクション (fork,pipe,dup)) によるメッセージの送受信

プロセス間通信 (リダイレクション (fork,pipe,dup)) により、親子プロセス間にてメッセージの送受信を行う例です。

dup (or dup2) によるリダイレクション用い、標準入出力をパイプで接続し通信を行っています。
リダイレクションを用いることにより、プロセス間の通信に高水準入出力関数を用いることが可能となります。

子側はプロセスの終了とともにファイルディスクリプタが閉じられ、親側の受信の受信が完了します。

親から子へ 実行結果

子から親へ 実行結果

プロセス間通信 (fork,pipe) によるメッセージの送受信

プロセス間通信 (fork,pipe) により、親子プロセス間にてメッセージの送受信を行う例です。

親から子へメッセージを送信する場合には、親側の送信の最後にファイルディスクリプタを閉じなければ(close(pipe_fd[1]); の部分)、子側の受信が完了せず、プロセスが終了しない点に注意して下さい。

子側はプロセスの終了とともにファイルディスクリプタが閉じられ、親側の受信の受信が完了します。

双方向通信や高水準入出力関数を用いた例は こちら

親から子へ 実行結果 子から親へ

実行結果

2011年9月2日金曜日

子プロセスの起動

fork 関数により子プロセスを起動し、別プロセスにて処理を開始するための例題です。

今回は、子プロセス内にて数値を1秒後とにインクリメントして表示し、子プロセス自身が自らで終了しています。

外部からの入力等が無い限り終了しない、等の処理を行うことも可能です。

子プロセスは、システムに別のプロセスとしてきちんと認識されますので、タスクマネージャーや ps コマンドにより PID を指定して強制終了することも可能です。

例題では親プロセスの PID を表示していますので、親プロセスと同じ名前で PID が異なるものが子プロセスとなります。 実行結果

2011年4月14日木曜日

親・子プロセス間でのメモリ共有

子プロセスを起動し、親・子プロセス間でメモリを共有しデータのやりとりを行う例題です。

例題では、親プロセスから生成された子プロセスは、親プロセスが持っていたメモリ(変数)をコピーし情報のやりとりを行っています。
その際、親・子プロセス両方から読み書き可能なメモリ領域を作って情報をやりとりする必要があります。
それを実現するのが共有メモリです。

共有メモリの取得後、削除せずに終了した場合、その共用メモリはOSが終了するまで残ってしまいます。
このようなメモリはipcsコマンドで見ることができ、ipcrmにより削除することが可能です。
(共有メモリを利用するプログラム起動中に ipcrm を行うと、release_sharemem 関数にて、"shmctl: Invalid argument" というようなエラーメッセージが表示されます。その辺はきちんと排他制御的なコードを考える必要はあります:セマフォ等)

今回の例題では a(int型)のデータのみ共用していますが、共有する情報は構造体にまとめて共有するのが便利であるため、共有メモリは構造体として宣言しています。

例題の動作は、親プロセスにより子プロセスが終了するのを待ち、a が 0 でなければプログラムを終了し、メモリを削除、a が 0 であれば、再びプロセスを作成し同じ処理を続行するようになっています。


例題に用いた関数は以下のもの。
shmget() 共有メモリの識別子を得る
shmat() 自プロセスのメモリとして割り当てる
shmdt() 自プロセスのメモリから外す
shmctl() 共有メモリの制御を行う(共有メモリの削除も可能)

子プロセスが起動した状態をアクティビティモニタにより確認した様子:

(Path Finder から tcsh を起動し、その後 make でソースをコンパイル・実行しているので、list_xxx のコマンドがそれ以降の階層に表示されており、さらに子プロセスが起動しているのが分かります。)


共有メモリを削除し忘れた場合の削除方法

実行結果