В this предыдущий вопрос Я отправил большую часть своего собственного кода оболочки. Мой следующий шаг - реализовать выполнение переднего плана и фонового процесса и должным образом дождаться их завершения, чтобы они не оставались «зомби».Как правильно дождаться процессов переднего плана/фона в моей собственной оболочке в C?
Прежде чем добавить возможность запускать их в фоновом режиме, все процессы выполнялись на переднем плане. И для этого я просто вызвал wait (NULL) после выполнения любого процесса с помощью execvp(). Теперь я проверяю символ «&» как последний аргумент, и если он есть, запустите процесс в фоновом режиме, не вызвав wait (NULL), и процесс может успешно работать в фоновом режиме, и я вернусь в свою оболочку.
Это все работает правильно (я думаю), проблема в том, что мне также нужно вызвать wait() (или waitpid()?) Так или иначе, чтобы фоновый процесс не оставался «зомби». Это моя проблема, я не знаю, как это сделать ...
Я считаю, что мне приходится обрабатывать SIGCHLD и делать что-то там, но мне еще нужно понять, когда посылается сигнал SIGCHLD, потому что я пытался также add wait (NULL) для childSignalHandler(), но это не сработало, потому что, как только я выполнил процесс в фоновом режиме, была вызвана функция childSignalHandler(), и, следовательно, wait (NULL), что означает, что я ничего не мог сделать с моей оболочкой, пока не завершится «фоновый» процесс. Что больше не выполнялось на фоне из-за ожидания в обработчике сигнала.
Что мне не хватает во всем этом?
Наконец-то, часть этого упражнения, мне также нужно распечатать изменения состояния процессов, например, завершение процесса. Таким образом, любое понимание этого также очень ценится.
Это мой полный код на данный момент:
#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;
}
Спасибо, но мне действительно нужно использовать обработчик сигнала, это часть упражнения. –
Я только что видел ваше редактирование ... Я положил waitpid() в обработчик сигнала, но у меня есть проблема, которую вы описываете во втором абзаце. Я просто не хотел использовать глобальные переменные, чтобы исправить проблему, но я не уверен, как ее исправить без них ... –
Избегание глобальных переменных хорошо, но общение с обработчиком сигналов - это один из тех случаев, необходимо. – dwc