프로세스를 통해 통신하기 위해 3개의 fifo 세트(파이프라고 함)를 생성하는 프로그램을 작성 중인데 실행이 중단되는 위치를 찾았지만 이유를 알 수 없어서 이제 중단되었습니다.
를 사용할 때 실행이 중단되는 것을 발견했습니다 fgetc()
. 전달된 파일 스트림은 fgetc()
함수가 반환한 FILE*입니다 fdopen()
. 이것은 실패한 기능입니다.샘플 1:
void mapear(int numProceso, int col, int val, char *signo)
{
int ncol=0, fdSplit, fdBuf;
char nombrePipe[10], cadenaLlave[10000], cadenaValor[10000], caracter;
bool encontroCadena = false, yaEscribioValores = false, creado = false;
FILE *ptrLectura, *ptrEscritura;
sprintf(nombrePipe, "split%d", numProceso);
fdSplit = open(nombrePipe, O_RDWR);
if(fdSplit == -1)
printf("\n[ERROR]-No se pudo abrir el pipe split, se volvera a tratar despues.\n");
ptrLectura = fdopen(fdSplit, "r+");
sprintf(nombrePipe, "buf%d", numProceso);
fdBuf = open(nombrePipe, O_RDWR);
if(fdBuf == -1)
printf("\n[ERROR]-No se pudo abrir el pipe buf, se volvera a tratar despues.\n");
while((caracter = fgetc(ptrLectura)) != EOF)
{
printf("REPITIENDO\n"); //DEBUG LINE 3: [NOT PRINTING ANYTHING] SHOWS THAT THE EXECUTION HANGS AFTER THE fgetc() CALL
/*Print something to fdBuf pipe*/
}
fclose(ptrLectura);
close(fdSplit);
close(fdBuf);
}
"REPITIENDO"를 인쇄해야 하는 줄이 실행되지 않습니다. 따라서 실행이 fgetc()
.
또한 mkfifo()
.mapear()
추신: 이는 호출될 때마다 열리는 동일한 fifo입니다. 샘플 2:
////////----CREATING THE FIRST SET OF PIPES AND OPENING THEM TO WRITE SOME REGISTERS TO EACH ONE----///////////
mode_t fifo_mode = S_IRUSR | S_IWUSR;
sprintf(nombrePipe, "split%d", cuentaArchivo);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
fd = open(nombrePipe, O_RDWR);
if(fd == -1)
printf("\n[ERROR]-No se pudo abrir el pipe split, se volvera a tratar despues.\n");
while (fgets(registro, sizeof registro, ptrLectura) != NULL)
{
//IF THE DESIRED NUMBER OF REGISTERS PER PIPE IS REACHED THEN CLOSE THE CURRENT PIPE AND OPEN THE NEXT ONE
if(cuentaRegistro == lineasPorArchivo)
{
close(fd);
printf("Cerrando pipe %s\n", nombrePipe);//DEBUG LINE 1: SHOWS THAT THE N PIPE IS BEING CLOSED
cuentaRegistro = 0;
cuentaArchivo++;
tieneHuerfana = false;
sprintf(nombrePipe, "split%d", cuentaArchivo);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
fd = open(nombrePipe, O_RDWR);
if(fd == -1)
printf("\n[ERROR]-No se pudo abrir el pipe split, se volvera a tratar despues.\n");
}
//WRITES REGISTER TO THE PIPE
dprintf(fd,"%s", registro);
cuentaRegistro++;
}
fclose(ptrLectura);
close(fd);
printf("Cerrando pipe %s\n", nombrePipe); //DEBUG LINE 2: SHOWS THAT THE LAST PIPE IS BEING CLOSED
////////----JUST CREATING THE SECOND SET OF PIPES----///////////
for(i = 1; i <= nmappers; i++)
{
sprintf(nombrePipe, "buf%d", i);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
}
////////----JUST CREATING THE THIRD SET OF PIPES----///////////
for(i = 1; i <= nreducers; i++)
{
sprintf(nombrePipe, "output%d", i);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
}
함수를 호출하는 예도 제공하겠습니다.void mapear(int numProceso, int col, int val, char *signo)
샘플 3:
////////----CREATING THE CHILD PROCESSES THAT ARE GOING TO CALL mapear()----///////////
pid_t mappers_pids[nmappers], reducers_pids[nreducers];
for(i = 1; i <= nmappers; i++)
{
if((pid = fork()) == 0)
{
signal(SIGCONT, handle_sigcont);
signal(SIGUSR1, handle_sigusr1);
pause();
mapear(i, col, val, signo);
kill(getppid, SIGCONT);
}
else if(pid < 0)
{
return -1;
}
//Padre
mappers_pids[i] = pid;
}
마지막으로, 자식이 호출할 수 있도록 자식에게 신호를 보내는 부모 프로세스의 예를 들어 보겠습니다.mapear()
샘플 4:
////////----FATHER SENDING SIGNALS TO IT'S CHILDS PROCESSES, SO THEY CAN CALL mapear()----///////////
for(i = 1; i <= nmappers; i++)
{
kill(mappers_pids[i], SIGCONT);
pause();
}
마지막 예에서는 부모 프로세스가 자식 프로세스에 신호를 보내는 것 외에도 pause()
현재 함수를 실행 중인 mapear()
자식 프로세스로부터 신호를 받을 때까지 기다립니다.
**PS: 실행 순서는 다음과 같습니다.
-샘플 2
-샘플 3
-샘플 4
-SAMPLE1(문제가 있다고 생각되는 부분)**
정말 감사합니다. 누군가가 도움을 줄 수 있기를 바랍니다!
업데이트: 재현 가능한 예제를 게시하라는 지시를 받았으므로 다음과 같습니다.
int main(int argc, char *argv[])
{
int i, pid, col, val, lineas, nmappers, nreducers, intermedios, lineasPorArchivo, lineasHuerfanas, bufsPorProceso, bufsHuerfanos, cuentaBuf = 1, fd;
int cuentaArchivo=1, cuentaRegistro=0;
bool salir = false, tieneHuerfana = false;
char *consulta = (char*) malloc(10);
char *signo = (char*) malloc(2);
FILE *ptrLectura, *ptrEscritura;
char registro[150], nombrePipe[10];
lineas = 16;
nmappers = 4;
nreducers = 2;
intermedios = 0;
lineasPorArchivo = lineas/nmappers;
lineasHuerfanas = lineas%nmappers;
ptrLectura = fopen("log16","r");
////////----CREATING THE FIRST SET OF PIPES AND OPENING THEM TO WRITE SOME REGISTERS TO EACH ONE----///////////
mode_t fifo_mode = S_IRUSR | S_IWUSR;
sprintf(nombrePipe, "split%d", cuentaArchivo);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
fd = open(nombrePipe, O_RDWR);
if(fd == -1)
printf("\n[ERROR]-No se pudo abrir el pipe split, se volvera a tratar despues.\n");
while (fgets(registro, sizeof registro, ptrLectura) != NULL)
{
//IF THE DESIRED NUMBER OF REGISTERS PER PIPE IS REACHED THEN CLOSE THE CURRENT PIPE AND OPEN THE NEXT ONE
if(cuentaRegistro == lineasPorArchivo)
{
close(fd);
printf("Cerrando pipe %s\n", nombrePipe);//DEBUG LINE 1: SHOWS THAT THE N PIPE IS BEING CLOSED
cuentaRegistro = 0;
cuentaArchivo++;
tieneHuerfana = false;
sprintf(nombrePipe, "split%d", cuentaArchivo);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
fd = open(nombrePipe, O_RDWR);
if(fd == -1)
printf("\n[ERROR]-No se pudo abrir el pipe split, se volvera a tratar despues.\n");
}
//WRITES REGISTER TO THE PIPE
dprintf(fd,"%s\n", registro);
cuentaRegistro++;
}
fclose(ptrLectura);
close(fd);
printf("Cerrando pipe %s\n", nombrePipe); //DEBUG LINE 2: SHOWS THAT THE LAST PIPE IS BEING CLOSED
////////----JUST CREATING THE SECOND SET OF PIPES----///////////
for(i = 1; i <= nmappers; i++)
{
sprintf(nombrePipe, "buf%d", i);
if(mkfifo(nombrePipe, fifo_mode) == -1)
return -1;
}
////////----CREATING THE CHILD PROCESSES THAT ARE GOING TO CALL mapear()----///////////
pid_t mappers_pids[nmappers], reducers_pids[nreducers];
for(i = 1; i <= nmappers; i++)
{
if((pid = fork()) == 0)
{
signal(SIGCONT, handle_sigcont);
signal(SIGUSR1, handle_sigusr1);
pause();
mapear(i, col, val, signo);
kill(getppid, SIGCONT);
}
else if(pid < 0)
{
return -1;
}
//Padre
mappers_pids[i] = pid;
}
sprintf(consulta, "4,=,0");
if(validarConsulta(consulta, &col, &val, &signo))
{
printf("\n[EN PROCESO]-Buscando registros de la columna %d que sean %s %d\n", col, signo, val);
////////----FATHER SENDING SIGNALS TO IT'S CHILDS PROCESSES, SO THEY CAN CALL mapear()----///////////
for(i = 1; i <= nmappers; i++)
{
kill(mappers_pids[i], SIGCONT);
pause();
}
printf("SUCCES!\n"); //EXECUTION SHOULD REACH THIS POINT WITHOUT HANGING
}
return 0;
}
bool validarConsulta(char *consulta, int *col, int *val, char **signo)
{
char *columna, *simbolo, *valor;
columna = strtok(consulta, ",");
*signo = strtok(NULL,",");
valor = strtok(NULL,",");
*col = atoi(columna);
*val = atoi(valor);
return (strcmp(*signo,"<") == 0 || strcmp(*signo,"<=") == 0 || strcmp(*signo,">") == 0 || strcmp(*signo,">=") == 0 || strcmp(*signo,"=") == 0);
}
void mapear(int numProceso, int col, int val, char *signo)
{
int fdSplit, fdBuf, cont = 0;
char nombrePipe[10], caracter;
FILE *ptrLectura, *ptrEscritura;
sprintf(nombrePipe, "split%d", numProceso);
fdSplit = open(nombrePipe, O_RDWR);
if(fdSplit == -1)
printf("\n[ERROR]-No se pudo abrir el pipe split, se volvera a tratar despues.\n");
ptrLectura = fdopen(fdSplit, "r+");
sprintf(nombrePipe, "buf%d", numProceso);
fdBuf = open(nombrePipe, O_RDWR);
if(fdBuf == -1)
printf("\n[ERROR]-No se pudo abrir el pipe buf, se volvera a tratar despues.\n");
printf("STUCK JUST BEFORE THE WHILE\n");
while((caracter = fgetc(ptrLectura)) != EOF)
{
printf("REPEATING %d\n", cont); //DEBUG LINE 3: [NOT PRINTING ANYTHING] SHOWS THAT THE EXECUTION HANGS AFTER THE fgetc() CALL
cont++;
/*Print something to fdBuf pipe*/
}
fclose(ptrLectura);
close(fdSplit);
close(fdBuf);
}
void handle_sigusr1(int sig)
{
printf("\nˑMapper con PID[%d] culmina.\n", getpid());
exit(0);
}
void handle_sigusr2(int sig)
{
printf("\nˑReducer con PID[%d] culmina.\n", getpid());
exit(0);
}
void handle_sigcont(int sig){
}
이제 실행은 mapear() 함수 호출에 도달하지도 않았습니다. 실행이 여전히 중단되지만 이제 SIGCONT 신호가 하위 프로세스로 전송됩니다.
PD: 예제가 제대로 작동하려면 예제 코드가 저장된 폴더에 "log16"이라는 파일을 찾아야 합니다. 파일은 다음과 같아야 합니다.
1 0 65 2592042 1 -1 1009884 -1 -1 -1 0 1 -1 -1 2 9 -1 -1
2 0 71 2592046 1 -1 1010132 -1 -1 -1 0 1 -1 -1 2 9 -1 -1
3 19 41 1893368 1 -1 1010108 -1 -1 -1 0 1 -1 -1 2 9 -1 -1
4 19 42 1825976 1 -1 2172 -1 -1 -1 0 1 -1 -1 2 9 -1 -1
5 516420 15 2592030 2 -1 4940 -1 -1 -1 0 2 -1 -1 1 8 -1 -1
6 1284365 26 2012962 1 -1 14088 -1 -1 -1 1 3 -1 -1 1 8 -1 -1
7 1284365 26 2290213 1 -1 13556 -1 -1 -1 1 3 -1 -1 1 8 -1 -1
8 1284365 28 2058925 1 -1 14124 -1 -1 -1 1 3 -1 -1 1 8 -1 -1
9 1284366 26 1782465 1 -1 14584 -1 -1 -1 1 3 -1 -1 1 8 -1 -1
10 1284366 27 1831699 1 -1 14112 -1 -1 -1 1 3 -1 -1 1 8 -1 -1
11 1389267 351 1573008 1 -1 351604 -1 -1 -1 0 4 -1 -1 1 8 -1 -1
12 1389297 332 1572997 1 -1 351028 -1 -1 -1 0 4 -1 -1 1 8 -1 -1
13 1477792 6 1484828 1 -1 351504 -1 -1 -1 0 4 -1 -1 1 8 -1 -1
14 1480061 23 1482543 1 -1 352136 -1 -1 -1 0 4 -1 -1 1 8 -1 -1
15 1666234 26 312610 1 -1 1690068 -1 -1 -1 0 5 -1 -1 2 11 -1 -1
16 1669900 9 262547 1 -1 1558900 -1 -1 -1 0 5 -1 -1 2 11 -1 -1