P0을 상위 프로세스로, P1,...,PN을 하위 프로세스로 사용하여 프로그램을 만들어야 합니다. 각 하위 항목은 파일에 대해 grep을 수행하고 파이프로 출력을 반환해야 합니다. 그런 다음 P0은 메시지를 읽고 줄 수를 세고 해당 숫자가 포함된 문장을 stdout에 인쇄해야 합니다. 문제는 시그널 13으로 인해 모든 어린이가 비자발적으로 해고된다는 점이다. 왜 이런 일이 발생합니까? 이것은 내 코드입니다.
#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
//eventuali define
#define MAXDIM 255
#define MAXPID 30
//global var declaration
int fd;
int pipefd[MAXPID][2];
//func declaration
void print_usage(char* prog_name);
void wait_child();
void codice_figlio(int index, char *word, char *filename);
void handler(int signo);
int conta_righe(char *str);
int main(int argc, char *argv[]) {
// local var declaration
int N = argc - 2;
int pid[MAXPID];
int i, num;
char buf[MAXDIM];
if (argc < 3) {
fprintf(stderr, "Numero di parametri non valido\n");
print_usage(argv[0]);
exit(EXIT_FAILURE);
}
for (i = 1; i <= N; i++) {
if ((fd = open(argv[i], O_RDONLY)) < 0) {
perror("Errore nell'apertura del file");
exit(EXIT_FAILURE);
}
close(fd);
}
signal(SIGUSR1, handler);
for (i = 0; i < N; i++) {
pid[i] = fork();
if (pipe(pipefd[i]) < 0) exit(-3);
if (!pid[i]) {
pause();
codice_figlio(i, argv[argc - 1], argv[i + 1]);
}
else if (pid[i] < 0) {
perror("fork error");
exit(-3);
}
sleep(1);
kill(pid[i], SIGUSR1);
close(pipefd[i][1]);
read(pipefd[i][0], buf, sizeof(int));
num = conta_righe(buf);
printf("Nel file %s sono state trovate %d occorrenze di %s.\n", argv[i + 1], num, argv[argc - 1]);
}
for (i = 0; i < N; i++) {
wait_child();
close(pipefd[i][0]);
close(pipefd[i][1]);
}
return 0;
}
void print_usage(char* prog_name){
fprintf(stderr, "Usage:\n\t%s file1 file2 ... fileN parola\n", prog_name);
}
void wait_child() {
int status, pid;
pid = wait(&status);
printf("*P0 (pid = %d): Terminato processo figlio PID = %d: ", getpid(), pid);
if ((char)status == 0) printf("Terminazione volontaria con stato %d\n", status>>8);
else printf("Terminazione involontaria per segnale %d\n", (char)status);
}
void codice_figlio(int index, char *word, char *filename) {
close(pipefd[index][0]);
close(1);
dup(pipefd[index][1]);
close(pipefd[index][1]);
execlp("/bin/grep", "grep", word, filename, (char*)0);
perror("Problemi con la grep");
exit(EXIT_FAILURE);
}
void handler(int signo) {
return;
}
int conta_righe(char *str) {
int res = 0, i = 0;
while (str[i] != '\0') {
if (str[i] == '\n') res++;
i++;
}
return res;
}
답변1
if (pipe(pipefd[i]) < 0)
이전 으로 이동됩니다 fork()
. 그렇지 않으면 두 개의 별도 파이프(상위 및 하위)를 생성하고 SIGPIPE
하위(함수에서)에서 파이프의 쓰기 끝을 닫으면 codice_figlio()
설명자가 아닌 참조에 대한 유일한 참조이기 때문에 를 얻게 됩니다. 부모와 자식 사이.
이것이 유일한 문제는 아닙니다. read(pipefd[i][0], buf, sizeof(int));
파이프에서 4바이트만 읽을 수 있지만 conta_righe()
함수는 그 안에 있는 행 수를 계산하려고 하기 때문에 문제가 있습니다. sizeof(int)
으로 변경됩니다 sizeof buf
.
그 후, 귀하의 코드는 다음과 같습니다무엇현명한:
$ ./fo fo.c fo.c pipefd
Nel file fo.c sono state trovate 8 occorrenze di pipefd.
Nel file fo.c sono state trovate 8 occorrenze di pipefd.
*P0 (pid = 9541): Terminato processo figlio PID = 9542: Terminazione volontaria con stato 0
*P0 (pid = 9541): Terminato processo figlio PID = 9543: Terminazione volontaria con stato 0
다음은 코드에 대한 패치입니다(수동으로 적용하면 사이트에서 탭이 구분됩니다).
--- fo.c~ 2020-04-20 20:51:19.540914204 +0300
+++ fo.c 2020-04-20 20:51:22.648914269 +0300
@@ -42,8 +42,8 @@
}
signal(SIGUSR1, handler);
for (i = 0; i < N; i++) {
- pid[i] = fork();
if (pipe(pipefd[i]) < 0) exit(-3);
+ pid[i] = fork();
if (!pid[i]) {
pause();
codice_figlio(i, argv[argc - 1], argv[i + 1]);
@@ -55,7 +55,7 @@
sleep(1);
kill(pid[i], SIGUSR1);
close(pipefd[i][1]);
- read(pipefd[i][0], buf, sizeof(int));
+ read(pipefd[i][0], buf, sizeof(buf));
num = conta_righe(buf);
printf("Nel file %s sono state trovate %d occorrenze di %s.\n", argv[i + 1], num, argv[argc - 1]);
}