
No.6ベストアンサー
- 回答日時:
プロセスを殺す処理は kill() を使いましょう、と toysmith さんが
書いてましたね。
kill(pid_c, SIGTERM);
です。
補足で「sig_handler とは?」とありますが、それはシグナルを処理する
為に書いた関数の名前です(関数名は何でもいい)。
一度、シグナルの処理をしてしまうと、初期状態に戻されてしまうので、
sig_handler() の中でも、signal() を使って、再登録しています。
ありがとうございました!
なんとか、子プロセスを終了することができました。
でも、まだまだわからない部分がいっぱいです。
もっと勉強しなくては。(^^ゞ
とにもかくにも、a-kumaさん、toysmithさんありがとうございました。
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);
}
ってな感じ。
この回答への補足
非常に申し訳ありません。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)
{
}
・・・・
/* プロセスを殺す処理? */
}
=======================
上記のようなプログラムになるのでしょうか?
子プロセスを殺す処理はどうなるのでしょうか?
ちなみに子プロセスはシェルです。
質問ばかりで申し訳ありません。よろしくお願い致します。
No.4
- 回答日時:
unix系なら「お行儀良い終了要求」としてSIGTERMが用意されているので子プロセス(fork(2)だと生成されるのはスレッドではなくプロセス)でSIGTERMをトラップ(signal(2))してexit(2)した方が良いでしょう。
<defunct>はいわゆる「ゾンビ-プロセス」で、死にぞこなった状態です。
unixでは「親は子を産んだら死ぬまで面倒を目る」という決まりがあります。
子の死んだときの面倒(死に水を取るようなもの)の見方は…
wait(2)で子プロセスの終了を待つだけです。
親プロセスと子プロセスが同時に実行しなければいけない場合、安易にwait(2)すると親プロセスが止まって(=子プロセスの終了待ち)しまいます。
この場合は子プロセスをinitプロセスに里子に出すことでゾンビー化を回避できます。
initは全てのプロセスの先祖であり、全ての親無しプロセスを養子として迎え入れます。
子プロセスをinitに里子に出す方法はsignal(2)でSIGCHLDを無視するように設定ます。
ただ、子の方法にも問題があります。
多数の子プロセスを生成した場合、単一の子プロセスを狙い撃ちで里子に出すことが出来ません。
この場合は少々ややこしい制御が必要になります。
シェルで実現しているので不可能ではありませんが…。
この回答への補足
>親プロセスと子プロセスが同時に実行しなければいけない場合、安易にwait(2)すると親プロセスが止まって(=子プロセスの終了待ち)しまいます。
>この場合は子プロセスをinitプロセスに里子に出すことでゾンビー化を回避できます。
> initは全てのプロセスの先祖であり、全ての親無しプロセスを養子として迎え入れます。
>子プロセスをinitに里子に出す方法はsignal(2)でSIGCHLDを無視するように設定ます。
>ただ、子の方法にも問題があります。
>多数の子プロセスを生成した場合、単一の子プロセスを狙い撃ちで里子に出すことが出来ません。
>この場合は少々ややこしい制御が必要になります。
>シェルで実現しているので不可能ではありませんが…。
申し訳ありません。
プログラムは具体的にどうなるのでしょうか。
ご教授ください。
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によって違いがありますので御確認下さい。
この回答への補足
プロセス名でなんとかなるのかなあって思っていたのですが、確かにプロセス名だと、複数いたときどうする?っていう問題がありますね。
ところで、以下のように子スレッドを起動したとき、子スレッドを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>となっています。
これはどうしてですか?
回避策はあるのでしょうか。
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 を参照して下さい。
No.1
- 回答日時:
unixを前提に考えると
親プロセスID:getppid(2)
自プロセスID:getpid(2)
子プロセスID:fork(2)の関数値
でわかると思います。
詳しくはmanでman 2 getpidなどとしてください。
(()内の数字がmanの第2パラメータ)
環境によって他にもやり方はあると思いますが上記の方法ならほとんどのunixで可能です。
この回答への補足
toysmithさんにはいつもいろいろ教えていただいてお世話になってます。
上記の件、確認したところ、IDが取れました。
ところで、もうひとつ追加質問なのですが、親とか、子のプロセスでなく、
まったく関係ないプロセスのプロセスIDをとることは可能ですか??
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Vba Replace関数について教えて...
-
DLLファイルの逆コンパイラにつ...
-
逆コンパイルと逆アセンブルの...
-
CSSが全く分かりません、お助け...
-
プログラマー達は何故、プログ...
-
Windows Formアプリからコンソ...
-
次の日本語の意味を教えて下さい
-
プログラム言語について c言語...
-
バッチファイルで以下のような...
-
Cのプログラムからアクセスでき...
-
C#でTreeViewのCheckBoxのサイ...
-
c#のTLS1.2での通信について
-
今ってプログラミング言語は何...
-
gccを行ってもexeファイルが生...
-
最初に聞かれたこと
-
プログラミング言語についてc++...
-
PIC12F1822でLED調光器を作りたい
-
C言語について(初心者)
-
プログラミングc++を全く分か...
-
C# で 数式文字列処理を処理す...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
CSSが全く分かりません、お助け...
-
DLLファイルの逆コンパイラにつ...
-
プログラマー達は何故、プログ...
-
C言語の関数のextern宣言
-
c言語
-
プログラミングc++を全く分か...
-
C言語について(初心者)
-
C言語 関数、変数の宣言について
-
あってる
-
Windows Formアプリからコンソ...
-
大量のデータを読み込んで表示...
-
visual studio 2022でのC#プロ...
-
逆コンパイルと逆アセンブルの...
-
DNCL(共テ用プログラミング言語...
-
VisualStudio2022でC言語プログ...
-
【C言語】全角文字の配列を、全...
-
C言語のことです。写真(見にく...
-
C#でログファイルにファイルパ...
-
C# で 数式文字列処理を処理す...
-
C#でTreeViewのCheckBoxのサイ...
おすすめ情報