当后跟execlp()时是否需要关闭管道?
在陈述我的问题之前,我已经阅读了一些关于堆栈溢出的相关问题,例如,和其他一些问题,但没有澄清我的困惑 首先是代码,这是第4版第13章“开始Linux编程”中的示例代码:当后跟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
#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()
)将调用进程的进程映像替换为指定程序的副本。