双向处理与C中的管道通信

时间:2015-03-05 04:07:29

标签: c pipe posix two-way

我正在尝试在c中创建一个程序,它可以使用两个独立的管道进行双向通信。

汇总;

  1. 父亲写入pipe1
  2. 孩子从pipe1读取并进行计算
  3. 孩子在pipe2中写下答案
  4. 父亲从pipe2
  5. 读取信息

    直到第3步一切顺利,如果我从第4点评论代码然后它全部工作,我甚至检查写入pipe2它似乎工作,但当我尝试从父亲的pipe2读取代码它挂起,甚至不执行子计算,第2步和第3步。请帮助我。到目前为止,这是我的代码。

    int main(int argc, char *argv[]) {
    
    pid_t pid;
    pid_t* trabajadores;
    
    int nHijos = 1;
    
    trabajadores = (pid_t*)malloc(sizeof(pid_t) * nHijos);
    
    int** aHijos;
    int links = 0;
    
    // Matriz de pipes
    aHijos = (int **) malloc(sizeof(int *) * nHijos);
    for (i = 0; i < nHijos; i++) {
        aHijos[i] = (int *) malloc(sizeof(int)*2);
    }
    
    int alPadre[2];
    pipe(alPadre);
    
    // Se crea el pool de procesos
    for (i = 0; i < nHijos; i++) {
    
        pipe(aHijos[i]);
        pid = fork();
    
        if (pid == 0) {
    
            int j;
            FILE* salidaHijo;
            FILE* entradaHijo;
            char buffer2[1024];
            close(alPadre [0]);
            for (j = 0; j<i; j++) {
                close(aHijos[j][0]);
                close(aHijos[j][1]);
            }
            close(aHijos[i][1]);
    
            entradaHijo = fdopen(aHijos[i][0], "r");
    
    
            // STEP 2
            while ( !feof (entradaHijo) &&  fgets (buffer2, sizeof (buffer2), entradaHijo) != NULL) {
                buffer2[strcspn(buffer2, "\n")] = 0;
            }
    
            char* resultado;
    
    
            /* CALCULATIONS */
    
    
    
    
    
    // STEP 3
            salidaHijo = fdopen(alPadre[1], "w");
            printf("%i\n", fprintf(salidaHijo, "%s\n", resultado));
            fflush (salidaHijo);
    
            exit(0);
    
        } else {
            trabajadores[i] = 0;
            close(alPadre[1]);
            close(aHijos[i][0]);
    
    
            // STEP 1
            FILE** salidaPadre;
            salidaPadre = (FILE**)malloc(sizeof(FILE*) * nHijos);
            for (i = 0; i < nHijos; i++) {
                salidaPadre[i] = fdopen(aHijos[i][1], "w");
            }
            fprintf(salidaPadre[j], "%s\n", DesencolarT(trabajos));
            trabajadores[j] = 1;
    
    
            sleep(5);
    
    
            // STEP 4
            char buffer[1024];
            entradaPadre = fdopen(alPadre[0], "r");
            read(alPadre[0], buffer, sizeof(buffer));
            while ( !feof (entradaPadre) &&  fgets (buffer, sizeof (buffer), entradaPadre) != NULL) {
                printf("%s\n", buffer);
    
            }
        }
    }
    return 0; 
    }
    

    不会编译它只是我的代码的粘贴部分,这是两个进程的strace -ff -o test.log ./myProg的输出。

    getdents(4, /* 0 entries */, 32768)     = 0
    fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 0), ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7761000
    write(1, ". 160\n", 6)                  = 6
    fcntl64(6, F_GETFL)                     = 0x1 (flags O_WRONLY)
    fstat64(6, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7760000
    _llseek(6, 0, 0xbfb8895c, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
    read(3, 0xbfb89738, 1024)               = ? ERESTARTSYS (To be restarted)
    --- SIGINT (Interrupt) @ 0 (0) ---
    +++ killed by SIGINT +++
    

    close(3)                                = 0
    close(6)                                = 0
    fcntl64(5, F_GETFL)                     = 0 (flags O_RDONLY)
    fstat64(5, {st_mode=S_IFIFO|0600, st_size=0, ...}) = 0
    mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7761000
    _llseek(5, 0, 0xbfb8895c, SEEK_CUR)     = -1 ESPIPE (Illegal seek)
    read(5, 0xb7761000, 4096)               = ? ERESTARTSYS (To be restarted)
    --- SIGINT (Interrupt) @ 0 (0) ---
    

    谢谢,抱歉西班牙语的长篇文章和可怕的格式。


    在第1步和第3步之后使用fflush()我得到了一个点,如果我在第1步之后关闭pipe1()一切正常,问题是我将来要继续写那个孩子所以我可以'关闭它。

1 个答案:

答案 0 :(得分:1)

在您的父级中,您不希望将管道的写入侧关闭到父级close(alPadre[1]);,因为后续的子级将无法使用该管道与父级通信。

实际上,您在后续循环迭代中对close(alPadre[1]);的后续调用可能会无意中关闭父级中的其他“随机”文件描述符,因为它将关闭恰好位于该位置的任何文件描述符编号alPadre[1]时间。关闭任何文件描述符后,您可能希望将该变量的值设置为-1,以便不使用该变量进一步调用将产生任何影响。

作为另一个例子,在您的子进程中,您为所有j&lt; close(aHijos[j][0]);调用aHijos[j][0]一世。这里再次说明,大多数这些文件描述符之前都是在fork之前被父级关闭,所以你再次“随机”关闭恰好在{{1}}的所有j&lt;岛

此外,您的父母最终需要关闭它用于与每个孩子交谈的管道的写入侧,否则孩子将在其输入循环中永远等待更多输入。这可能是你的父母在第4步挂起的原因,因为你的孩子在第2步被绞死,等待来自父母的管道上的EOF。