
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も見ています
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
-
大麻の使用罪がなかった理由や法改正での変更点、他国との違いを弁護士が解説
ドイツで2024年4月に大麻が合法化され、その2ヶ月後にサッカーEURO2024が行われた。その際、ドイツ警察は大会運営における治安維持の一つの方針として「アルコールを飲んでいるグループと、大麻を吸っているグループ...
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
DLLファイルの逆コンパイラにつ...
-
プログラミングc++を全く分か...
-
大量のデータを読み込んで表示...
-
Notepad++の関数リスト表示の変...
-
gccを行ってもexeファイルが生...
-
visual studio 2022でのC#プロ...
-
プログラマー達は何故、プログ...
-
C言語 関数、変数の宣言について
-
QT(C++)の学習方法について
-
int16_t の _t は何?
-
ディスプレイの解像度とマウス...
-
C言語で、変数名を引数として渡...
-
c言語でイベントフラグを使った...
-
逆コンパイルと逆アセンブルの...
-
Notepad++の関数リスト表示でC...
-
c言語
-
【C言語】全角文字の配列を、全...
-
C言語の関数のextern宣言
-
c++の勉強方法を教えてくださ...
-
C言語について。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
c言語
-
gccを行ってもexeファイルが生...
-
大量のデータを読み込んで表示...
-
visual studio 2022でのC#プロ...
-
C++でデスクトップGUIアプリ開...
-
【C言語】全角文字の配列を、全...
-
Windows Formアプリからコンソ...
-
VisualStudio2022でC言語プログ...
-
C#でログファイルにファイルパ...
-
C#でTreeViewのCheckBoxのサイ...
-
c#のTLS1.2での通信について
-
VisualStudioでC++クラスを追加...
-
C言語について。
-
int16_t の _t は何?
-
プログラマー達は何故、プログ...
-
逆コンパイルと逆アセンブルの...
-
C言語の関数のextern宣言
-
c言語でイベントフラグを使った...
-
C言語 関数、変数の宣言について
-
[C言語]fputsとfprintfの違い
おすすめ情報