質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.30%
bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

1回答

530閲覧

bashスクリプトで生成した子プロセスがゾンビ状態にならない理由を教えてください

dam9806

総合スコア21

bash

bash(Bourne-again-Shell)は sh(Bourne Shell)のインプリメンテーションに様々な機能が追加されたシェルです。LinuxやMac OS XではBashはデフォルトで導入されています。

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

1グッド

0クリップ

投稿2023/09/18 06:04

編集2023/09/18 06:08

以下のbashスクリプトとC言語プログラムは、子プロセスがゾンビ状態になるのを確認したく作成したものです。しかし、bashスクリプトの方は、ゾンビ状態になりません。C言語プログラムを模倣してbashスクリプトを作ったつもりです。なぜ、bashスクリプトの方は、子プロセスがゾンビ状態にならないのでしょうか?

なお、ゾンビ状態の確認方法は、プログラム実行後にps lを実行して、<defunct>が表示されるか否かで判断しています。

bash

1#!/bin/bash 2sleep 1 & 3pid=$! 4sleep 30 5wait $pid 6echo "return code=$?" 7exit 0

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <sys/types.h> 4#include <sys/wait.h> 5#include <unistd.h> 6 7int main(){ 8 int i; 9 if(fork()==0){ 10 if (execl("/bin/sleep","/bin/sleep","1",NULL)<0){ 11 exit(EXIT_FAILURE); 12 } 13 } 14 else{ 15 sleep(30); 16 wait(&i); 17 printf("return code=%d\n",WEXITSTATUS(i)); 18 } 19 return EXIT_SUCCESS; 20}
melian👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dam9806

2023/09/18 08:32

コメントありがとうございます。リンク先を確認しましたが、疑問の解消には至っておりません。。
otn

2023/09/18 11:14

Bashのソースを読んでなくて想像ですが、ジョブコントロールの都合上からSIGCHLDをトラップしてwaitしているのではないでしょうか。
dam9806

2023/09/18 11:59 編集

コメントありがとうございます。bashスクリプトを実行しているbashプロセスが子プロセス(上の例の場合は sleep 1 のプロセス)の完了(SIGCHLD送出)をトラップし、プロセステーブルからその子プロセスを抹消しているということでしょうかね。
otn

2023/09/18 12:21

はい。そんな気がします。 プロセステーブルからの削除はOSの仕事なので、bashとしてはwaitするだけですが。
guest

回答1

0

sigaction(2)

NOTES

POSIX.1-1990 disallowed setting the action for SIGCHLD to SIG_IGN. POSIX.1-2001 and later allow this possibility, so that ignoring SIGCHLD can be used to prevent the creation of zombies (see wait(2)).

wait(2)

NOTES

POSIX.1-2001 specifies that if the disposition of SIGCHLD is set to SIG_IGN or the SA_NOCLDWAIT flag is set for SIGCHLD (see sigaction(2)), then children that terminate do not become zombies and a call to wait() or waitpid() will block until all children have terminated, and then fail with errno set to ECHILD. (The original POSIX standard left the behavior of setting SIGCHLD to SIG_IGN unspecified. Note that even though the default disposition of SIGCHLD is "ignore", explicitly setting the disposition to SIG_IGN results in different treatment of zombie process children.)

なので、C のコードに例えば signal(SIGCHLD, SIG_IGN); を追加するとゾンビ化しません。

c

1 : 2#include <signal.h> 3 4int main(){ 5 int i; 6 signal(SIGCHLD, SIG_IGN); 7 8 if(fork()==0){ 9 :

参考までに、Linux の strace コマンドで bash スクリプトの実行処理を追ってみると以下の様になっています。

bash

1$ strace -t -f -e /clone,/exec,/wait bash test.sh 204:29:35 execve("/usr/bin/bash", ["bash", "test.sh"], 0x7ffd28ec6988 /* 77 vars */) = 0 304:29:35 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f67061fda10) = 362589 4strace: Process 362589 attached 5[pid 362588] 04:29:35 clone(child_stack=NULL, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x7f67061fda10) = 362590 6strace: Process 362590 attached 7[pid 362589] 04:29:35 execve("/usr/bin/sleep", ["sleep", "1"], 0x556a82292730 /* 77 vars */ <unfinished ...> 8[pid 362588] 04:29:35 wait4(-1, <unfinished ...> 9[pid 362589] 04:29:35 <... execve resumed>) = 0 10[pid 362590] 04:29:35 execve("/usr/bin/sleep", ["sleep", "30"], 0x556a82296830 /* 77 vars */) = 0 11[pid 362589] 04:29:36 +++ exited with 0 +++ 12[pid 362588] 04:29:36 <... wait4 resumed>[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 362589 13[pid 362588] 04:29:36 wait4(-1, <unfinished ...> 14[pid 362590] 04:30:05 +++ exited with 0 +++ 1504:30:05 <... wait4 resumed>[{WIFEXITED(s) && WEXITSTATUS(s) == 0}], 0, NULL) = 362590 1604:30:05 --- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=362589, si_uid=1000, si_status=0, si_utime=0, si_stime=0} --- 1704:30:05 wait4(-1, 0x7ffe79ccb1d0, WNOHANG, NULL) = -1 ECHILD (No child processes) 18return code=0 1904:30:05 +++ exited with 0 +++

投稿2023/09/18 19:34

melian

総合スコア21216

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.30%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問