execlp() 无法检索正确的输入
execlp() failing to retrieve correct input
我一直在尝试编写一个非常简单的程序,其中 parent 进程通过管道将 100 行代码传递给 child 进程。 child 然后应该使用生成的行并在这些行上执行命令行程序 more
。
但是,当我尝试 运行 程序时,它就死机了。我很小心地关闭了所有未被两个进程使用的描述符,但我真的不明白是什么导致了它。
代码:
int main(void){
int fd[2];
if (pipe(fd) == -1){
perror("Error creating pipe");
return 1;
}
dup2(fd[1], STDOUT_FILENO);
int i;
for (i = 1; i <= 100; i++){
printf("Line %d\n", i);
}
close(fd[1]);
pid_t pid = fork();
if(pid == 0) {
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execlp("more", "more",(char*) NULL);
fprintf(stderr, "Failed to execute 'more'\n");
exit(1);
}
wait(NULL);
return 0;
}
I was careful to close all descriptors not being used by both processes
不是真的。
dup2(fd[1], STDOUT_FILENO);
这里你制作stdout
一份fd[1]
。
close(fd[1]);
您在这里关闭 fd[1]
,但 stdout
仍处于打开状态。
那你fork
。此时两个进程都可以通过 stdout
.
访问管道的写端
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
在子进程中,您将 fd[0]
复制到 stdin
并关闭 fd[0]
。
然后,当您执行 more
时,它仍然可以访问管道的两端(通过 stdin
/ stdout
)。
同时您的父进程可以访问管道的两端(通过 fd[0]
/ stdout
)。
实际上你什么都没关闭。
还有第二个问题:您的父进程写入 stdout
,它绑定到管道的写入端,没有任何人读取它。根据您写入的量,stdout
是行缓冲还是块缓冲,stdout
缓冲区有多大,以及您的管道本身可以存储多少,这本身可能会死锁。如果管道满了并且周围没有人读取它,printf
就会阻塞。
要解决此问题,请不要在父进程中 dup2
并且在子进程启动之前不要写入管道。
int main(void){
int fd[2];
if (pipe(fd) == -1){
perror("Error creating pipe");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("Error spawning process");
return 2;
}
if (pid == 0) {
close(fd[1]); /* close write end of the pipe in the child */
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execlp("more", "more", (char*)NULL);
fprintf(stderr, "Failed to execute 'more'\n");
exit(1);
}
close(fd[0]); /* close read end of the pipe in the parent */
FILE *fp = fdopen(fd[1], "w");
if (!fp) {
perror("Error opening file handle");
return 3;
}
for (int i = 1; i <= 100; i++){
fprintf(fp, "Line %d\n", i);
}
fclose(fp); /* flush and close write end of the pipe in the parent */
wait(NULL);
return 0;
}
我一直在尝试编写一个非常简单的程序,其中 parent 进程通过管道将 100 行代码传递给 child 进程。 child 然后应该使用生成的行并在这些行上执行命令行程序 more
。
但是,当我尝试 运行 程序时,它就死机了。我很小心地关闭了所有未被两个进程使用的描述符,但我真的不明白是什么导致了它。
代码:
int main(void){
int fd[2];
if (pipe(fd) == -1){
perror("Error creating pipe");
return 1;
}
dup2(fd[1], STDOUT_FILENO);
int i;
for (i = 1; i <= 100; i++){
printf("Line %d\n", i);
}
close(fd[1]);
pid_t pid = fork();
if(pid == 0) {
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execlp("more", "more",(char*) NULL);
fprintf(stderr, "Failed to execute 'more'\n");
exit(1);
}
wait(NULL);
return 0;
}
I was careful to close all descriptors not being used by both processes
不是真的。
dup2(fd[1], STDOUT_FILENO);
这里你制作stdout
一份fd[1]
。
close(fd[1]);
您在这里关闭 fd[1]
,但 stdout
仍处于打开状态。
那你fork
。此时两个进程都可以通过 stdout
.
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
在子进程中,您将 fd[0]
复制到 stdin
并关闭 fd[0]
。
然后,当您执行 more
时,它仍然可以访问管道的两端(通过 stdin
/ stdout
)。
同时您的父进程可以访问管道的两端(通过 fd[0]
/ stdout
)。
实际上你什么都没关闭。
还有第二个问题:您的父进程写入 stdout
,它绑定到管道的写入端,没有任何人读取它。根据您写入的量,stdout
是行缓冲还是块缓冲,stdout
缓冲区有多大,以及您的管道本身可以存储多少,这本身可能会死锁。如果管道满了并且周围没有人读取它,printf
就会阻塞。
要解决此问题,请不要在父进程中 dup2
并且在子进程启动之前不要写入管道。
int main(void){
int fd[2];
if (pipe(fd) == -1){
perror("Error creating pipe");
return 1;
}
pid_t pid = fork();
if (pid == -1) {
perror("Error spawning process");
return 2;
}
if (pid == 0) {
close(fd[1]); /* close write end of the pipe in the child */
dup2(fd[0], STDIN_FILENO);
close(fd[0]);
execlp("more", "more", (char*)NULL);
fprintf(stderr, "Failed to execute 'more'\n");
exit(1);
}
close(fd[0]); /* close read end of the pipe in the parent */
FILE *fp = fdopen(fd[1], "w");
if (!fp) {
perror("Error opening file handle");
return 3;
}
for (int i = 1; i <= 100; i++){
fprintf(fp, "Line %d\n", i);
}
fclose(fp); /* flush and close write end of the pipe in the parent */
wait(NULL);
return 0;
}