Trong this câu hỏi trước tôi đã đăng hầu hết mã shell của riêng mình. Bước tiếp theo của tôi là thực hiện tiến trình nền trước và nền và thực hiện đúng cách để chúng kết thúc, vì vậy chúng không tồn tại dưới dạng "thây ma".Làm thế nào để đúng cách chờ đợi các quy trình nền trước/nền trong vỏ của riêng tôi trong C?
Trước khi thêm khả năng chạy chúng trong nền, tất cả các quy trình đang chạy ở nền trước. Và cho rằng, tôi chỉ đơn giản gọi là chờ đợi (NULL) sau khi thực hiện bất kỳ quá trình với execvp(). Bây giờ, tôi kiểm tra ký tự '&' là đối số cuối cùng và nếu nó ở đó, chạy quá trình trong nền bằng cách không gọi chờ (NULL) và quá trình có thể chạy vui vẻ trong nền tôi sẽ quay trở lại shell của tôi.
Đây là tất cả hoạt động đúng (tôi nghĩ), vấn đề bây giờ, là tôi cũng cần phải gọi wait() (hoặc waitpid()?) Bằng cách nào đó để quá trình nền không còn "zombie". Đó là vấn đề của tôi, tôi không chắc chắn làm thế nào để làm điều đó ...
Tôi tin rằng mình phải xử lý SIGCHLD và làm điều gì đó ở đó, nhưng tôi chưa hiểu đầy đủ khi tín hiệu SIGCHLD được gửi vì tôi cũng cố gắng thêm wait (NULL) vào childSignalHandler() nhưng nó không hoạt động vì ngay sau khi tôi thực hiện một tiến trình trong nền, hàm childSignalHandler() đã được gọi và do đó, sự chờ đợi (NULL), có nghĩa là tôi không thể làm bất cứ điều gì với vỏ của tôi cho đến khi quá trình "nền" kết thúc. Mà đã không chạy trên nền nữa vì sự chờ đợi trong xử lý tín hiệu.
Tôi thiếu gì trong tất cả điều này?
Một điều cuối cùng, một phần của bài tập này tôi cũng cần in các thay đổi của trạng thái quy trình, như chấm dứt quá trình. Vì vậy, bất kỳ cái nhìn sâu sắc về điều đó cũng thực sự được đánh giá cao.
Đây là mã đầy đủ của tôi vào lúc này:
#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;
}
Cảm ơn, nhưng tôi thực sự cần sử dụng trình xử lý tín hiệu, đó là một phần của bài tập. –
Tôi chỉ nhìn thấy chỉnh sửa của bạn ... Tôi đã đặt waitpid() vào bộ xử lý tín hiệu nhưng tôi có vấn đề bạn mô tả trong đoạn thứ hai của bạn. Tôi không muốn sử dụng các biến toàn cục để khắc phục sự cố nhưng tôi không chắc cách sửa lỗi mà không có chúng ... –
Tránh các biến toàn cục là tốt, nhưng giao tiếp với trình xử lý tín hiệu là một trong những trường hợp chúng ' cần thiết. – dwc