如何使用 dup2 将标准输入和标准输出重定向到管道文件描述符?
How to use dup2 to redirect stdin and stdout to pipe file descriptors?
我试图分叉一个进程,并将 parent 的标准输出重定向到管道的写入端,将 child 的标准输入重定向到管道的读取端。 child 应该读取整数,直到 parent 打印出零。 parent 从 1 打印到 3,然后打印 0。parent 和 child 都打印它们开始和结束的时间。因为 parent 无法打印到标准输出,所以它会将它的开始和结束时间发送到 child 并且 child 打印它的开始时间和结束时间以及 parents 开始时间和结束时间。我本可以使用 dup 并将 stdout 重定向到另一个文件描述符,但我选择让它变得简单。该程序非常简单,但我得到的输出不符合场景。
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd[2];
int p = pipe(fd);
int ch = fork();
if (ch)
{
// Parent - Counts from 1 to 3
int dp = dup2(fd[1], 1);
printf("Cnt_Started_at_%d\n", time(NULL));
for (int i = 0; i <= 3; i++)
{
printf("Parent %d\n", i);
sleep(1);
}
printf("0\n");
printf("Cnt_Finished_at_%d\n", time(NULL));
}
else
{
// Child - Terminated by 0
int dp = dup2(fd[0], 0);
printf("Trm_Started_at_%d\n", time(NULL));
char buffer[100];
scanf("%s", buffer);
printf("%s\n", buffer);
int i;
while (scanf("Parent %d", &i) && i)
printf("Recieved: %d\n", i);
scanf("%s", buffer);
printf("%s\n", buffer);
printf("Trm_Finished_at_%d\n", time(NULL));
}
}
输出:
Trm_Started_at_1578295974
Cnt_Started_at_1578295974
Parent
Trm_Finished_at_1578295978
根本问题是使用 'scanf %s' 来阅读消息。回想一下,'%s' 在遇到白色 space 时将停止读取,并将白色 space 放回缓冲区。
来自家长的初始消息是 'Cnt_Started_at_1234\n'。此子进程将读取令牌,但会将尾随的“\n”留在缓冲区中。
接下来家长会发送 'Parent 0\n'。 Child 将尝试解析这是 scanf("Parent %d", &i) && i)
。这里有两个问题:
- 'Parent' 中的 'P' 将与初始消息中剩余的“\n”不匹配
- 当格式更新为跳过前导spaces时,'i'的值将为零,这将导致
while
读取[=33=后退出].
可能的解决方案:允许 scanf 跳过 spaces,并消除 i
上的条件
while (scanf(" Parent %d", &i) == 1 )
printf("Recieved: %d\n", i);
这里的问题出在你的 scanf 语句上。按照@dash-o 的建议,将其更改为处理空格。
另一个问题是,首先i = 0
。您需要修改 while 以适应 0。
由于您仅在 while loop
中评估 i
,因此您不会进入“i=0”案例。
下面是修改后的程序和输出,另外,请添加各种检查 return 函数值/缓冲区溢出,如您认为正确 --
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd[2];
int p = pipe(fd);
int ch = fork();
if (ch)
{
// Parent - Counts from 1 to 3
int dp = dup2(fd[1], 1);
printf("Cnt_Started_at_%d\n", time(NULL));
for (int i = 0; i <= 3; i++)
{
printf("Parent %d\n", i);
sleep(1);
}
printf("0\n");
printf("Cnt_Finished_at_%d\n", time(NULL));
}
else
{
// Child - Terminated by 0
int dp = dup2(fd[0], 0);
printf("Trm_Started_at_%d\n", time(NULL));
char buffer[100];
scanf("%s", buffer);
printf("%s\n", buffer);
int i;
while (scanf(" Parent %d", &i) && i >= 0) // notice change here ...
printf("Recieved: %d\n", i);
scanf("%s", buffer);
printf("%s\n", buffer);
printf("Trm_Finished_at_%d\n", time(NULL));
}
}
OUTPUT --
$ ./main.out
Trm_Started_at_1578303662
Cnt_Started_at_1578303662
Recieved: 0
Recieved: 1
Recieved: 2
Recieved: 3
0
Trm_Finished_at_1578303666
我试图分叉一个进程,并将 parent 的标准输出重定向到管道的写入端,将 child 的标准输入重定向到管道的读取端。 child 应该读取整数,直到 parent 打印出零。 parent 从 1 打印到 3,然后打印 0。parent 和 child 都打印它们开始和结束的时间。因为 parent 无法打印到标准输出,所以它会将它的开始和结束时间发送到 child 并且 child 打印它的开始时间和结束时间以及 parents 开始时间和结束时间。我本可以使用 dup 并将 stdout 重定向到另一个文件描述符,但我选择让它变得简单。该程序非常简单,但我得到的输出不符合场景。
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd[2];
int p = pipe(fd);
int ch = fork();
if (ch)
{
// Parent - Counts from 1 to 3
int dp = dup2(fd[1], 1);
printf("Cnt_Started_at_%d\n", time(NULL));
for (int i = 0; i <= 3; i++)
{
printf("Parent %d\n", i);
sleep(1);
}
printf("0\n");
printf("Cnt_Finished_at_%d\n", time(NULL));
}
else
{
// Child - Terminated by 0
int dp = dup2(fd[0], 0);
printf("Trm_Started_at_%d\n", time(NULL));
char buffer[100];
scanf("%s", buffer);
printf("%s\n", buffer);
int i;
while (scanf("Parent %d", &i) && i)
printf("Recieved: %d\n", i);
scanf("%s", buffer);
printf("%s\n", buffer);
printf("Trm_Finished_at_%d\n", time(NULL));
}
}
输出:
Trm_Started_at_1578295974
Cnt_Started_at_1578295974
Parent
Trm_Finished_at_1578295978
根本问题是使用 'scanf %s' 来阅读消息。回想一下,'%s' 在遇到白色 space 时将停止读取,并将白色 space 放回缓冲区。
来自家长的初始消息是 'Cnt_Started_at_1234\n'。此子进程将读取令牌,但会将尾随的“\n”留在缓冲区中。
接下来家长会发送 'Parent 0\n'。 Child 将尝试解析这是 scanf("Parent %d", &i) && i)
。这里有两个问题:
- 'Parent' 中的 'P' 将与初始消息中剩余的“\n”不匹配
- 当格式更新为跳过前导spaces时,'i'的值将为零,这将导致
while
读取[=33=后退出].
可能的解决方案:允许 scanf 跳过 spaces,并消除 i
上的条件 while (scanf(" Parent %d", &i) == 1 )
printf("Recieved: %d\n", i);
这里的问题出在你的 scanf 语句上。按照@dash-o 的建议,将其更改为处理空格。
另一个问题是,首先i = 0
。您需要修改 while 以适应 0。
由于您仅在 while loop
中评估 i
,因此您不会进入“i=0”案例。
下面是修改后的程序和输出,另外,请添加各种检查 return 函数值/缓冲区溢出,如您认为正确 --
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>
int main()
{
int fd[2];
int p = pipe(fd);
int ch = fork();
if (ch)
{
// Parent - Counts from 1 to 3
int dp = dup2(fd[1], 1);
printf("Cnt_Started_at_%d\n", time(NULL));
for (int i = 0; i <= 3; i++)
{
printf("Parent %d\n", i);
sleep(1);
}
printf("0\n");
printf("Cnt_Finished_at_%d\n", time(NULL));
}
else
{
// Child - Terminated by 0
int dp = dup2(fd[0], 0);
printf("Trm_Started_at_%d\n", time(NULL));
char buffer[100];
scanf("%s", buffer);
printf("%s\n", buffer);
int i;
while (scanf(" Parent %d", &i) && i >= 0) // notice change here ...
printf("Recieved: %d\n", i);
scanf("%s", buffer);
printf("%s\n", buffer);
printf("Trm_Finished_at_%d\n", time(NULL));
}
}
OUTPUT --
$ ./main.out
Trm_Started_at_1578303662
Cnt_Started_at_1578303662
Recieved: 0
Recieved: 1
Recieved: 2
Recieved: 3
0
Trm_Finished_at_1578303666