当后跟execlp()时是否需要关闭管道?

当后跟execlp()时是否需要关闭管道?,c,pipe,dup,C,Pipe,Dup,在陈述我的问题之前,我已经阅读了一些关于堆栈溢出的相关问题,例如,和其他一些问题,但没有澄清我的困惑 首先是代码,这是第4版第13章“开始Linux编程”中的示例代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> int main() { int data_processed; int file_pipes[2]; const cha

在陈述我的问题之前,我已经阅读了一些关于堆栈溢出的相关问题,例如,和其他一些问题,但没有澄清我的困惑

首先是代码,这是第4版第13章“开始Linux编程”中的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main()
{
int data_processed;
int file_pipes[2];
const char some_data[] = "123";
pid_t fork_result;

if (pipe(file_pipes) == 0)
   {
    fork_result = fork();
    if (fork_result == (pid_t)-1)
       {
        fprintf(stderr, "Fork failure");
        exit(EXIT_FAILURE);
       }

    if (fork_result == (pid_t)0)  // Child process
       {
        close(0);
        dup(file_pipes[0]);
        close(file_pipes[0]);   // LINE A
        close(file_pipes[1]);   // LINE B

        execlp("od", "od", "-c", (char *)0);
        exit(EXIT_FAILURE);
       }
    else    // parent process
       {
        close(file_pipes[0]);   // LINE C
        data_processed = write(file_pipes[1], some_data,
                               strlen(some_data));
        close(file_pipes[1]);   // LINE D
        printf("%d - wrote %d bytes\n", (int)getpid(), data_processed);
       }
   }
exit(EXIT_SUCCESS);
}
#包括
#包括
#包括
#包括
int main()
{
已处理的int数据;
int文件_管道[2];
const char some_data[]=“123”;
pid_t fork_结果;
if(管道(文件_管道)==0)
{
fork_result=fork();
if(fork\u result==(pid\u t)-1)
{
fprintf(标准“叉故障”);
退出(退出失败);
}
if(fork\u result==(pid\u t)0)//子进程
{
关闭(0);
dup(文件_管道[0]);
关闭(文件[0]);//行A
关闭(文件[1]);//行B
execlp(“od”、“od”、“-c”、(char*)0);
退出(退出失败);
}
else//父进程
{
关闭(文件[0]);//行C
数据处理=写入(文件管道[1],一些数据,
斯特伦(一些数据);
关闭(文件[1]);//第D行
printf(“%d-写入了%d字节\n”,(int)getpid(),数据已处理);
}
}
退出(退出成功);
}
执行结果是:

momo@xue5:~/TestCode/IPC\u管道$/a.out

10187-写入3个字节

momo@xue5:~/TestCode/IPC_管道$00000001 2 3

0000003

momo@xue5:~/TestCode/IPC\u管道$

如果您对A行、C行和D行进行了注释,则结果与上面相同。 我了解结果,子节点通过连接到管道的自己的标准输入从其父节点获取数据,并将“od-c”结果发送到其标准输出

但是,如果您对第B行进行了注释,结果将是:

momo@xue5:~/TestCode/IPC\u管道$/a.out

10436-写入3个字节

momo@xue5:~/TestCode/IPC\u管道$

没有“od-c”结果 由execlp()启动的“od-c”是否未执行,或者其输出是否未定向到stdout?一种可能性是'od'的read()被阻止,因为如果您对行B进行注释,子级的写入文件描述符文件_管道[1]是打开的。但是注释行D使父级的写入文件描述符文件_管道[1]打开,仍然可以有'od-c'输出

还有,为什么我们需要在execlp()之前关闭管道?execlp()将用“od”中的新映像替换进程映像,包括堆栈、.data、.heap、.text。这是否意味着,即使不关闭子级中的文件_管道[0]和文件_管道[1]作为行A和B,文件_管道[0]和文件_管道[1]仍将被execlp()“销毁”?从代码的结果来看,它不是。但我错在哪里呢

非常感谢您在这里花费的时间和精力~~

当后跟execlp()时是否需要关闭管道

严格来说,这不是必需的,因为这取决于管道的使用方式。但一般来说,如果过程不需要
管道
端,则应将其关闭

为什么我们需要在execlp()之前关闭管道?execlp()将替换进程映像

因为文件描述符(默认情况下)在
exec
调用中保持打开状态。从:“默认情况下,文件描述符在execve()中保持打开状态。在exec上标记为关闭的文件描述符将关闭;请参阅fcntl(2)中对FD_CLOEXEC的描述。”

然而,如果你评论了B行,…没有“od-c”结果

这是因为
od
进程从
stdin
读取数据,直到获得
EOF
。如果进程本身没有关闭
文件管道[1]
,那么它将不会看到
EOF
,因为管道的写入端不会被所有打开它的进程完全关闭

如果您对A行、C行和D行进行了注释,则结果与上面相同


这是因为A和C处的文件描述符是管道的读取端,不会阻止任何人等待它关闭(如上所述)。D处的文件描述符是写入端,不关闭它确实会导致问题。但是,即使代码没有显式调用该文件描述符上的
close
,它仍将被关闭,因为进程退出

当后跟execlp()时是否需要关闭管道

严格来说,这不是必需的,因为这取决于管道的使用方式。但一般来说,如果过程不需要
管道
端,则应将其关闭

为什么我们需要在execlp()之前关闭管道?execlp()将替换进程映像

因为文件描述符(默认情况下)在
exec
调用中保持打开状态。从:“默认情况下,文件描述符在execve()中保持打开状态。在exec上标记为关闭的文件描述符将关闭;请参阅fcntl(2)中对FD_CLOEXEC的描述。”

然而,如果你评论了B行,…没有“od-c”结果

这是因为
od
进程从
stdin
读取数据,直到获得
EOF
。如果进程本身没有关闭
文件管道[1]
,那么它将不会看到
EOF
,因为管道的写入端不会被所有打开它的进程完全关闭

如果您对A行、C行和D行进行了注释,则结果与上面相同


这是因为A和C处的文件描述符是管道的读取端,不会阻止任何人等待它关闭(如上所述)。D处的文件描述符是写入端,不关闭它确实会导致问题。但是,即使代码没有显式调用该文件描述符上的
close
,它仍将被关闭,因为进程退出

还有,为什么我们需要在execlp()之前关闭管道?execlp()将用“od”中的新映像替换进程映像,包括堆栈、.data、.heap、.text

是的,exec系列函数(包括
execlp()
)将调用进程的进程映像替换为指定程序的副本。