この前の質問では、私自身のシェル コードのほとんどを投稿しました。私の次のステップは、フォアグラウンドとバックグラウンドのプロセス実行を実装し、それらが終了するのを適切に待って、「ゾンビ」のままにならないようにすることです。
バックグラウンドで実行する可能性を追加する前は、すべてのプロセスがフォアグラウンドで実行されていました。そのために、execvp() でプロセスを実行した後、単純に wait(NULL) を呼び出しました。ここで、最後の引数として「&」文字をチェックし、そこにある場合は、wait(NULL) を呼び出さずにバックグラウンドでプロセスを実行します。プロセスはバックグラウンドで正常に実行され、シェルに戻ります。
これはすべて正常に機能しています (私は思います)。現在の問題は、バックグラウンド プロセスが「ゾンビ」のままにならないように、何らかの方法で wait() (または waitpid() ?) を呼び出す必要があることです。それは私の問題です、私はそれを行う方法がわかりません...
私は SIGCHLD を処理し、そこで何かをしなければならないと信じていますが、wait(NULL) を childSignalHandler() に追加しようとしたため、SIGCHLD シグナルがいつ送信されるかをまだ完全には理解していませんが、機能しませんでした。バックグラウンドでプロセスを実行すると、childSignalHandler() 関数が呼び出され、その結果、wait(NULL) が呼び出されました。つまり、「バックグラウンド」プロセスが終了するまでシェルで何もできませんでした。シグナルハンドラーで待機しているため、バックグラウンドで実行されなくなりました。
このすべてで何が欠けていますか?
最後にもう 1 つ、この演習の一環として、プロセスの終了など、プロセスの状態の変化も出力する必要があります。したがって、それに関する洞察も本当に高く評価されています。
これは現時点での私の完全なコードです:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <wait.h>
#include <signal.h>
#include <sys/types.h>
#include "data.h" // Boolean typedef and true/false macros
void childSignalHandler(int signum) {
//
}
int main(int argc, char **argv) {
char bBuffer[BUFSIZ], *pArgs[10], *aPtr = NULL, *sPtr;
bool background;
ssize_t rBytes;
int aCount;
pid_t pid;
//signal(SIGINT, SIG_IGN);
signal(SIGCHLD, childSignalHandler);
while(1) {
write(1, "\e[1;31mmyBash \e[1;32m# \e[0m", 27);
rBytes = read(0, bBuffer, BUFSIZ-1);
if(rBytes == -1) {
perror("read");
exit(1);
}
bBuffer[rBytes-1] = '\0';
if(!strcasecmp(bBuffer, "exit")) {
exit(0);
}
sPtr = bBuffer;
aCount = 0;
do {
aPtr = strsep(&sPtr, " ");
pArgs[aCount++] = aPtr;
} while(aPtr);
background = FALSE;
if(!strcmp(pArgs[aCount-2], "&")) {
pArgs[aCount-2] = NULL;
background = TRUE;
}
if(strlen(pArgs[0]) > 1) {
pid = fork();
if(pid == -1) {
perror("fork");
exit(1);
}
if(pid == 0) {
execvp(pArgs[0], pArgs);
exit(0);
}
if(!background) {
wait(NULL);
}
}
}
return 0;
}