我正在编写一个程序,在其中创建 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”的行没有被执行......所以执行甚至没有进入 while,因为它挂在fgetc()
.
我还发布了我使用 . 创建 fifo 的示例mkfifo()
。mapear()
PS:这些是每次被调用时打开的相同 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