关闭管道获取错误的文件描述符

标签 c pipe

这是代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

int main(int argc, char **argv) {

int num = 2;
pid_t pid;
int i;

int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
    if (pipe(p1[i]) == -1) {
        perror("pipe");
        exit(1);
    }
    if (pipe(p2[i]) == -1) {
        perror("pipe");
        exit(1);
    }
}

for (i = 0; i < num; i++) {
    if ((pid = fork()) == 0) {
        if (close(p1[i][1]) != 0) {
            perror("close");
            exit(1);
        }
        if (close(p2[i][0]) != 0) {
            perror("close");
            exit(1);
        }
        printf("%d\n", getpid());
        exit(0);
    } else if (pid > 0) {
        if (close(p1[i][0]) != 0) {
            perror("close");
            exit(1);
        }
        if (close(p2[i][1]) != 0) {
            perror("close");
            exit(1);
        }
        continue;
    } else {
        perror("fork");
        exit(1);
    }   
}

for (i = 0; i < num; i++) {
    if (close(p1[i][0]) != 0) {
        perror("close1"); // <----error
    }
    if (close(p1[i][1]) != 0) {
        perror("close");
    }
    if (close(p2[i][0]) != 0) {
        perror("close");
    }
    if (close(p2[i][1]) != 0) {
        perror("close2"); // <----error
    }
}
for (i = 0; i < num; i++) {
    if (wait(NULL) == -1) {
        perror("wait");
        exit(1);
    }
}
return 0;
}

当我运行它时,它会给我这个输出

close1: Bad file descriptor
close2: Bad file descriptor
close1: Bad file descriptor
close2: Bad file descriptor
8798
8799

我想做的是创建两个管道的二维数组并 fork num 次。 创建和运行工作正常,但有些管道无法关闭。 看起来 p1[i][0] 和 p2[i][1] 永远不会更接近。

最佳答案

您收到 EBADFD 的原因是您尝试关闭同一个文件描述符两次。

我在第一段代码中添加了一条打印语句来显示/跟踪正在关闭的文件描述符。如果您编译并运行它,您将看到在您第二次尝试关闭描述符后立即出现错误消息。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

int main(int argc, char **argv) {

int num = 1;
pid_t pid;
int i;

int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
    if (pipe(p1[i]) == -1) {
        perror("pipe");
        exit(1);
    }
    if (pipe(p2[i]) == -1) {
        perror("pipe");
        exit(1);
    }
}

for (i = 0; i < num; i++) {
    if ((pid = fork()) == 0) {
        printf("Child closing: Pipe1 %d End %d\n", i, 1);
        if (close(p1[i][1]) != 0) {
            perror("close");
            exit(1);
        }
        printf("Child closing: Pipe2 %d End %d\n", i, 1);
        if (close(p2[i][0]) != 0) {
            perror("close");
            exit(1);
        }
        printf("%d\n", getpid());
        exit(0);
    } else if (pid > 0) {
        printf("Parent closing: Pipe1 %d End %d\n", i, 0);
        if (close(p1[i][0]) != 0) {
            perror("close");
            exit(1);
        }
        printf("Parent closing: Pipe1 %d End %d\n", i, 1);
        if (close(p2[i][1]) != 0) {
            perror("close");
            exit(1);
        }
        continue;
    } else {
        perror("fork");
        exit(1);
    }   
}

for (i = 0; i < num; i++) {
    printf("Closing: Pipe1: %d End: %d\n", i, 0);
    if (close(p1[i][0]) != 0) {
        perror("close1"); // <----error
    }
    printf("Closing: Pipe1: %d End: %d\n", i, 1);
    if (close(p1[i][1]) != 0) {
        perror("close");
    }
    printf("Closing: Pipe2: %d End: %d\n", i, 0);
    if (close(p2[i][0]) != 0) {
        perror("close");
    }
    printf("Closing: Pipe2: %d End: %d\n", i, 1);
    if (close(p2[i][1]) != 0) {
        perror("close2"); // <----error
    }
}
for (i = 0; i < num; i++) {
    if (wait(NULL) == -1) {
        perror("wait");
        exit(1);
    }
}
return 0;
}

检查pid并关闭第一个循环内未关闭的末端。此代码假设您正在根据 child / parent 的需要在特定管道上进行读写。您可能需要根据您的用例进行调整:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>

int main(int argc, char **argv) {

int num = 1;
pid_t pid;
int i;

int p1[num][2], p2[num][2];
for (i = 0; i < num; i++) {
    if (pipe(p1[i]) == -1) {
        perror("pipe");
        exit(1);
    }
    if (pipe(p2[i]) == -1) {
        perror("pipe");
        exit(1);
    }
}

for (i = 0; i < num; i++) {
    if ((pid = fork()) == 0) {
        if (close(p1[i][1]) != 0) {
            perror("close");
            exit(1);
        }
        if (close(p2[i][0]) != 0) {
            perror("close");
            exit(1);
        }
        printf("%d\n", getpid());
        exit(0);
    } else if (pid > 0) {
        if (close(p1[i][0]) != 0) {
            perror("close");
            exit(1);
        }
        if (close(p2[i][1]) != 0) {
            perror("close");
            exit(1);
        }
        continue;
    } else {
        perror("fork");
        exit(1);
    }   
}

for (i = 0; i < num; i++) {
    if (pid == 0) {
        if (close(p1[i][0]) != 0) {
            perror("close1");
        }
        if (close(p2[i][1]) != 0) {
            perror("close");
        }
    } else {
        if (close(p1[i][1]) != 0) {
            perror("close");
        }
        if (close(p2[i][0]) != 0) {
            perror("close2");
        }
    }
}
for (i = 0; i < num; i++) {
    if (wait(NULL) == -1) {
        perror("wait");
        exit(1);
    }
}
return 0;
}

关于关闭管道获取错误的文件描述符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36294135/

相关文章:

c - 如何在c中检查给定的二进制地址是ipv4还是ipv6

c - atmega16 串行通信不工作(uart_send 和 uart_receive)

c - C 中进程之间的管道

c++ - 如何在 C++ 中将密码通过管道传递给 ssh?

c - 在 shell 中实现管道

c - Fprintf VS _ftprintf

c - 外部库文件链接错误: C project

c - HDF5 属性 unsigned long long 值

angular - 在 observable<Object> 上使用异步管道并将其绑定(bind)到 html 中的局部变量

c - 如何锁定具有多个读取进程的 PIPE(或 FIFO)?