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で質問しましょう!
似たような質問が見つかりました
- その他(学校・勉強) この中で間違ってある説明はありますか?詳しい方に教えていただきたいです。 A. 1つのプログラムが複 2 2023/07/14 01:15
- Windows 10 バッチファイルでのエクスプローラー終了 1 2022/05/30 14:32
- 哲学 真実の信仰=真理の探究 1 2022/11/26 09:03
- 環境学・エコロジー 二酸化炭素の排出 1 2023/08/07 16:40
- 医学 医学に詳しい方にお尋ね致します。 摂取した水分は最終的には尿になりますが、そのプロセスがよく分かりま 4 2023/01/16 14:57
- 政治 私は文部科学省ヘ入り込んで投稿した私の建議文を彼らが私の依頼まましましょうか。? 2 2023/08/22 07:08
- CPU・メモリ・マザーボード 今のCPUは2nmプロセスとか何やらで製造されているかと思いますが、このスケールをどんどん大きくして 3 2023/06/07 20:34
- 数学 x^5+15x-44=0について、解き方のプロセスを誰か教えてください 3 2023/02/22 17:09
- その他(ソフトウェア) ソフトが異常終了します 1 2022/08/28 01:41
- Windows 10 Windows 10のエクスプローラーの表示が遅いのですが 4 2023/02/04 09:34
このQ&Aを見た人はこんなQ&Aも見ています
-
プロが教える店舗&オフィスのセキュリティ対策術
中・小規模の店舗やオフィスのセキュリティセキュリティ対策について、プロにどう対策すべきか 何を注意すべきかを教えていただきました!
-
c言語でプロセスIDを調べたい
C言語・C++・C#
-
実行プログラム名の取得
C言語・C++・C#
-
プロセスIDからウィンドウハンドルを取得する方法
C言語・C++・C#
-
-
4
コマンド(例えばls)の出力結果を文字列で取得するプログラムの作成方法
C言語・C++・C#
-
5
popenした子プロセスのプロセスIDを知る方法は?
C言語・C++・C#
-
6
<unistd.h>をVisualStudioでつかえるようにする
C言語・C++・C#
-
7
スレッドの安全な終了のさせ方
C言語・C++・C#
-
8
fopne で失敗する原因
C言語・C++・C#
-
9
GDBデバッガの使い方について
C言語・C++・C#
-
10
CStringのFindで文字列検索を行いたいのですが
C言語・C++・C#
-
11
C言語におけるif文の評価順
C言語・C++・C#
-
12
実行時のコマンドプロンプトを非表示 Visual C++
C言語・C++・C#
-
13
C++のfor文について
C言語・C++・C#
-
14
シェルスクリプトでファイル内の数値文字列を数値として扱うには
その他(プログラミング・Web制作)
-
15
acceptをalarmでタイムアウトさせる処理がうまくいきません
C言語・C++・C#
-
16
子プロセスの状態を親プロセスに渡したい
C言語・C++・C#
-
17
CString ←→ BSTRの変換について
C言語・C++・C#
-
18
別のプロセスの関数を呼び出す方法はありますか?
C言語・C++・C#
-
19
main.c:7:43: warning: implicit declaration of func
C言語・C++・C#
-
20
C++で入力した文字列から数字を取り除くもしくは数字のみをのこす
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ArduinoのジャイロモジュールMP...
-
C言語をコンパイルするとコンピ...
-
mallocについて
-
gccを行ってもexeファイルが生...
-
c言語
-
C言語 列挙型(enum型)変数について
-
卒業研究でよく分からないとこ...
-
C言語初心者 構造体 課題について
-
C++でデスクトップGUIアプリ開...
-
C言語初心者 構造体 課題について
-
win10で、正確な待ち時間の作り方
-
[C言語]fputsとfprintfの違い
-
VisualStudio2022でC言語プログ...
-
大量のデータを読み込んで表示...
-
C言語初心者 ポインタについて...
-
あなたは、Excelはどうやって学...
-
C言語初心者です、、、お助けく...
-
システムエンジニアの適正について
-
Stuck
-
Notepad++の関数リスト表示の変...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
gccを行ってもexeファイルが生...
-
あなたは、Excelはどうやって学...
-
WindowsのCapsLock(キャップス...
-
質問失礼します。 プログラム言...
-
double型が正常に認識されてい...
-
Notepad++の関数リスト表示でC...
-
どちのほうがすきですか?
-
Stuck
-
Notepad++の関数リスト表示の変...
-
ArduinoでMouse関数を使用して...
-
C言語の関数と配列に関する質問
-
C言語って古いですか?
-
Linuxでの開発環境構築や設定の...
-
Bitcoin、BTCはブロックチェー...
-
C++6.0でのresource.hについて
-
MACで動く実行ファイルをWindow...
-
C言語 列挙型(enum型)変数について
-
c言語
-
大量のデータを読み込んで表示...
-
こんなことてしますか??
おすすめ情報