• ベストアンサー

プロセスIDの取得方法 

Unix C++でプロセスIDの取得方法を教えてください。 (見当違いの質問だったらすみません) 親プロセス(自分)のプロセスIDと、親プロセスの起動した子プロセスのプロセスIDを取得したいです。 また、親プロセスの起動した子プロセスのプロセスIDを使って親プロセス終了時に子プロセスをkillしたいと思うのですが、 具体的にどうすればいいかわからず困っています。

質問者が選んだベストアンサー

  • ベストアンサー
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.6

プロセスを殺す処理は kill() を使いましょう、と toysmith さんが 書いてましたね。   kill(pid_c, SIGTERM); です。 補足で「sig_handler とは?」とありますが、それはシグナルを処理する 為に書いた関数の名前です(関数名は何でもいい)。 一度、シグナルの処理をしてしまうと、初期状態に戻されてしまうので、 sig_handler() の中でも、signal() を使って、再登録しています。

noname#794
質問者

お礼

ありがとうございました! なんとか、子プロセスを終了することができました。 でも、まだまだわからない部分がいっぱいです。 もっと勉強しなくては。(^^ゞ とにもかくにも、a-kumaさん、toysmithさんありがとうございました。

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (5)

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.5

toysmith> 多数の子プロセスを生成した場合、単一の子プロセスを狙い撃ちで里子に出すことが出来ません 親プロセスで SIGCHLD を無視するのは、「細かいことは知らんよ」という場合に 限って、とした方が良いでしょう。 一般的には、親プロセスで SIGCHLD を捕捉して、wait() をする、というかたちを とります。 一番おおざっぱな形は以下のような感じ。 void sig_handler(int sig) {   wait(NULL);   signal(SIGCHLD, sig_handler); } int main(void) {   signal(SIGCHLD, sig_handler);   ... } もし、私がやるとしたら wait() よりも waitpid() を使うかな。 捕捉するシグナルが(親自身も含めて)ひとつとは限らないから、シグナルハンドラを ひとつにしておいて int sig_handler(int sig) {   if (sig == SIGCHLD)   {     int stat;     while (waitpid(-1, &stat, WNOHANG) > 0)     {       /* stat 次第では、何か処理が有るかも */     }   }   signal(sig, sig_handler); } ってな感じ。

noname#794
質問者

補足

非常に申し訳ありません。a-kumaさん、toysmithさん。 いまだによくわかりません。 言いたいことはわかる気がするのですが、どういうふうにプログラムを組めばよいのか・・・。 =============================== void sig_handler(int sig) {   wait(NULL);   signal(SIGCHLD, sig_handler);  /* sig_handlerとは? */ } int main(void) {   signal(SIGCHLD, sig_handler);   ...   pid_t pid_c;   pid_c = fork();   if(pid_c == 0)   {    execl("aa", NULL);   }   else if (pid_c < 0)   {   } ・・・・   /* プロセスを殺す処理? */       } ======================= 上記のようなプログラムになるのでしょうか? 子プロセスを殺す処理はどうなるのでしょうか? ちなみに子プロセスはシェルです。 質問ばかりで申し訳ありません。よろしくお願い致します。

全文を見る
すると、全ての回答が全文表示されます。
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.4

unix系なら「お行儀良い終了要求」としてSIGTERMが用意されているので子プロセス(fork(2)だと生成されるのはスレッドではなくプロセス)でSIGTERMをトラップ(signal(2))してexit(2)した方が良いでしょう。 <defunct>はいわゆる「ゾンビ-プロセス」で、死にぞこなった状態です。 unixでは「親は子を産んだら死ぬまで面倒を目る」という決まりがあります。 子の死んだときの面倒(死に水を取るようなもの)の見方は… wait(2)で子プロセスの終了を待つだけです。 親プロセスと子プロセスが同時に実行しなければいけない場合、安易にwait(2)すると親プロセスが止まって(=子プロセスの終了待ち)しまいます。 この場合は子プロセスをinitプロセスに里子に出すことでゾンビー化を回避できます。 initは全てのプロセスの先祖であり、全ての親無しプロセスを養子として迎え入れます。 子プロセスをinitに里子に出す方法はsignal(2)でSIGCHLDを無視するように設定ます。 ただ、子の方法にも問題があります。 多数の子プロセスを生成した場合、単一の子プロセスを狙い撃ちで里子に出すことが出来ません。 この場合は少々ややこしい制御が必要になります。 シェルで実現しているので不可能ではありませんが…。

noname#794
質問者

補足

>親プロセスと子プロセスが同時に実行しなければいけない場合、安易にwait(2)すると親プロセスが止まって(=子プロセスの終了待ち)しまいます。 >この場合は子プロセスをinitプロセスに里子に出すことでゾンビー化を回避できます。 > initは全てのプロセスの先祖であり、全ての親無しプロセスを養子として迎え入れます。 >子プロセスをinitに里子に出す方法はsignal(2)でSIGCHLDを無視するように設定ます。 >ただ、子の方法にも問題があります。 >多数の子プロセスを生成した場合、単一の子プロセスを狙い撃ちで里子に出すことが出来ません。 >この場合は少々ややこしい制御が必要になります。 >シェルで実現しているので不可能ではありませんが…。 申し訳ありません。 プログラムは具体的にどうなるのでしょうか。 ご教授ください。

全文を見る
すると、全ての回答が全文表示されます。
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.3

以下、unixという言葉はunix系OS(unix version 6~9,SystemIII/V、全てのBSD及びXENIXを含むベンダー系UNIX)とunixもどきOS(minix,linux,xinuなど)の共通部分を指しています。 OS固有の拡張によって実現可能な場合があるかもしれません。 「まったく関係ないプロセスのプロセスID」を取得する事は(一般的な方法としては)ありません。 unixはPIDでプロセスを認識する為、他の方法では一意にプロセスを特定するとこが出来ません。 unixには「プロセス名」という概念は無く、しいて言えば実行ファイル(=実行権を持ったスクリプトを含む)の名称がプロセス名とされます。 よって、1コマンドが多重に起動された場合は全てのコマンドが同じプロセス名となるため一意に認識できません。 繰り返しますが、プロセスを一意に特定する為のキーはPIDのみです。 a-kumaさんがおっしゃるようにOSの持つプロセス管理テーブルを参照する事である条件下(プロセスを多重起動しない)でのみ一意性が産まれます。 ただし、unixはマルチユーザ、マルチタスクである為、この方法には確実ではありません。 確実でない事を覚悟の上ならa-kumaさんのおっしゃる方法でPIDの取得は可能でしょう。 cm = popen("ps -e | awk '/inetd/{print $1}'", "r"); の方が効率はいいでしょう。 プロセス起動(fork(2)とexec(2))はシステムコールの中でも最も非効率です。 移植性が無くなってもよいなら/dev/kmemをオープンしてプロセス管理テーブルを直接読み込む方法もあります。 /dev/kmemはunixカーネルが管理するメモリ領域そのもので、ここを読めば全ての管理情報が取得可能です。 psもここを読んで表示しているので結果としては同じになります。 ただし、/dev/kmemのフォーマットはOSごとに(下手をするとバージョンごとに)違いますのでkmem.h参照してプロセス管理テーブルの位置とフォーマットを調べる必要があります。 kmem.hは/usr/include/sysか/usr/include/hardwareにある事が多いのですが、これもOSによって違いがありますので御確認下さい。

noname#794
質問者

補足

プロセス名でなんとかなるのかなあって思っていたのですが、確かにプロセス名だと、複数いたときどうする?っていう問題がありますね。 ところで、以下のように子スレッドを起動したとき、子スレッドをkillするにはどうしたらいいのでしょうか。kill(pid_c,SIGINT)ではできませんか? ======================= pid_t pid_c; pid_c = fork(); if(pid_c == 0) { execl("aa", NULL); } else if (pid_c < 0) { return -100; } ================================= また、ここで起動した子スレッドのaaなんですが、 psでみると、<defunct>となっています。 これはどうしてですか? 回避策はあるのでしょうか。

全文を見る
すると、全ての回答が全文表示されます。
  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.2

> 親とか、子のプロセスでなく、まったく関係ないプロセスのプロセスIDをとることは可能ですか?? 全く関係ないプロセスをどうやって特定しますか? 例えば、プロセス名が分かっているとしたら、一番汎用的なのは ps コマンドを 使うことです。例えば、inetd のプロセスIDを取得する場合、 FILE *cm; int pid; cm = popen("ps -e | grep inetd | awk '{print $1}'", "r"); fscanf(cm, "%d", &pid); ってな感じ。 後は、どんな unix でも、ってわけにはいかないのですが、プロセスファイル システムを使う手もあります。man proc を参照して下さい。

全文を見る
すると、全ての回答が全文表示されます。
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.1

unixを前提に考えると 親プロセスID:getppid(2) 自プロセスID:getpid(2) 子プロセスID:fork(2)の関数値 でわかると思います。 詳しくはmanでman 2 getpidなどとしてください。 (()内の数字がmanの第2パラメータ) 環境によって他にもやり方はあると思いますが上記の方法ならほとんどのunixで可能です。

noname#794
質問者

補足

toysmithさんにはいつもいろいろ教えていただいてお世話になってます。 上記の件、確認したところ、IDが取れました。 ところで、もうひとつ追加質問なのですが、親とか、子のプロセスでなく、 まったく関係ないプロセスのプロセスIDをとることは可能ですか??

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ウインドウのプロセス終了について

    今C++でタスクバーのウインドの列挙を行い、またプロセスIDの取得を できたのですがこれらを終了させる方法がわかりません。 いろいろ調べてみたのですが、UNIXでのkillコマンドに匹敵する 関数がわかりません。 自分が調べたところ使えそうなのは。 CloseMainWindow関数 TerminateProcess関数 などができそうなのではと考えています。 また http://akky.cjb.net/mfc/appclose.html ここに書いてあるソースを打ってみたのですが、 思うように動きませんでした。 どうしたらよいでしょうか。 具体的な方法(プログラム)がほしいです。 よろしくお願いします。

  • プロセスIDの取得方法について

    下に同様の質問をしたのですが、削除方法分からない為、再度質問させていただきまし。 VB5.0を利用しています。 VBで書いたexeを実行した際に、そのプロセスID(自分の)は、GetCurrentProcessIdを利用すれば取得できると分かりました。 が、プログラム内でExcelを下記の様にオブジェクトを作成した場合、そのプロセスIDをどうやって取得すればいいのでしょうか? ご存知の方居ましたら、教えて下さい。 Set ExcelObj = CreateObject("Excel.Application") ここで起動?されたExcelのプロセスIDを取得したいのですが。

  • プロセスIDの取得の方法。

    使用言語:C OS:NT4.0WS プロセスビューアで表示されるような、プロセスIDやプロセス名を 取得する方法を探しています。 Cの標準関数で無ければAPI関数での方法でもどちらでも構わないので よろしくお願いします。

  • プロセスIDの再利用

    こんちにちは、honiyonです。  親子関係のない全く別々に起動されたプロセスの終了するプログラムを作ろうと思います。  .NETではシステムで一意なIDというものがある、という情報を見かけたのですが、.NETは使用したくないのでプロセスIDを使って監視出来ないかと考えています。  プロセスIDを使って、定期的にポーリングする方法をとったとき、 プロセスIDが再利用されてしまう事で終了を検知出来ない事があるのではという疑問が出てきました。  UNIXでは極力重複しない(再利用しない)という方針があるようですが、Windowsではそのような仕組みはありますでしょうか?  そのような仕組みがあれば、再利用による検知ミスは無視出来るレベルの問題かなと考えています。    また、プロセスIDでの監視以外で良い手段がありましたら、是非ご教授頂ければ幸いです。  宜しくお願いします(..  

  • javaのプロセスについて

    UnixやLinuxなどで、javaのプロセスを常駐させたいのですが、何か方法はありますでしょうか。 javaという名前であれば何でもいいので、テスト的に起動したいです。 (プロセスをkillするテストをするために、使用します)

  • 起動しているアプリケーションのプロセスIDを取得したい.

    現在,起動しているアプリケーションのプロセスIDを取得したいと考えています. プロセスIDを取得するコマンドはあるのでしょうか? 環境:Windows2000+SP3

  • プロセスIDからウィンドウハンドルを取得する方法

    以下の方法を調べていますが、プロセスIDからウィンドウハンドルを取得する方法がわかりませんでした。 (1)自分がCreateProcessで生成したプロセスのウィンドウハンドル (2)自分とは関係ないプロセスで、プロセスIDだけ判明しているプロセスのウィンドウハンドル ご存知の方、ご教授願います。 <環境> WindowsXP VC++6.0

  • c言語でプロセスIDを調べたい

    unixのコマンドで ps aux と打つと "ユーザー名" "プロセスID"  。 。 。 。 がでますけど、この2番目の"プロセスID"を調べる関数ってありますか? ※というのも、プロセスID(ジョブ番号)を引数にして、そのプロセスが終了したら何か処理をさせるというプログラムを作りたいからです。よろしくお願いします。

  • 既存プロセスからプロセスのプライマリースレッドIDの取得方法

    いつもお世話になってます。 プロセスに関することで分からないことがあるため、どなたか御教授して下さい。 只今、VC++で開発を行っているのですが、CreateProcess関数を使用して開始したプロセスの情報が、引数で指定したPROCESS_INFORMATIONにプライマリースレッドのハンドルやIDが設定されるのは知っているのですが、現在動作中のプロセスからそのプロセスのプライマリースレッドのIDを取得することは可能でしょうか? 具体的には、動作中のプロセスIDを指定するとそのプロセスのプライマリースレッドに対してPostThreadMessageで任意のメッセージが送れるという仕様です。 対象のプロセスがウィンドウを持っていれば、EnumWindows関数を使用してウィンドウに対してPostMessageができるというのは分かったのですが、今回対象のプロセスがウィンドウを持たない為、上記のようにスレッドに対してメッセージを送るようになっています。 CreateProcess呼び出し時にはスレッドIDが取得できることから、プロセスID、または、プロセスハンドルからスレッドIDが取得できるのではないかなと考えられるんですが。。。。

  • 子プロセス、

    親プロセスから子プロセスを生成するとは具体的に何を意味しているのでしょうか? またresume文とはなんでしょうか? 何をしてくれているのでしょうか? なぜUNIXは安定していると言われるのでしょうか? 聞いたけど忘れてしまいました、 お願いします。

このQ&Aのポイント
  • 彼氏との関係に変化があり、乗り換えを検討している可能性がある
  • 彼氏が好みの子を探している様子があり、乗り換える可能性があるのか心配
  • 彼氏の行動に対して嫉妬や不安を感じており、試されているのかと思う
回答を見る

専門家に質問してみよう