【问题标题】:Two way processes communication with pipes in C两种方式处理与C中管道的通信
【发布时间】:2015-03-05 04:07:29
【问题描述】:

我正在尝试用 c 语言编写一个程序,它分叉一个孩子,并使用两个单独的管道进行双向通信。

总结;

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

在第 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() 一切正常,问题是我需要在未来继续写信给那个孩子,所以我可以'关闭它。

【问题讨论】:

  • 发布的代码无法编译,是不是缺少某些部分? (如果人们可以编译发布的代码以查看它如何工作/不适合他们,您将获得更好的帮助)
  • pipe 在标准 C99 或 C11 中不存在。这是一个 POSIX 或 Linux 调用。所以你应该用 POSIX 或 Linux 标记你的问题。

标签: c pipe posix two-way


【解决方案1】:

在您的父级中,您不想关闭父级close(alPadre[1]); 的管道写入端,因为这样您的后续子级将无法使用该管道与父级对话。

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

作为另一个示例,在您的子进程中,您为所有 j close(aHijos[j][0]);。同样,这些文件描述符中的大多数以前在分叉之前由父级关闭,因此您再次“随机”关闭所有 j aHijos[j][0]。

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

【讨论】:

  • 好吧,我不明白为什么我不应该在父代码中关闭 alpadre(1) 因为那是父亲用来从他的孩子那里读取的管道,写结束那个管子是给孩子们用的。好的,我现在有循环外的父代码,并且我没有关闭父亲中的alpadre(1),但仍然不起作用
  • 我无法关闭父进程的写入端,因为它是一个进程池,我希望能够将更多的工作从父进程发送给他的孩子,并使用第二个管道从他们那里得到答案
  • @Josepas 你的逻辑的主要问题是你的父母永远不会关闭管道的写入端给孩子(在发送适当的输入之后)。因此,孩子将在其输入循环中阻塞,因为它将永远等待来自父母的更多输入,直到它获得 EOF。关闭父管道的写入端将向该客户端发送 EOF,使其完成。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-27
  • 1970-01-01
  • 2019-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多