C语言 如何使用 dup2 将 stdin 和 stdout 重定向到管道文件描述符?



我试图分叉一个进程,并将父级的 stdout 重定向到管道的写入端,将孩子的 stdin 重定向到管道的读取端。子项应该读取整数,直到父项打印零。父级从 1 打印到 3,然后打印 0。父级和子级都打印开始和完成的时间。由于父级无法打印到 stdout,它会将其开始和结束时间发送给孩子,子级打印其开始时间和完成时间以及父级开始时间和完成时间。我本可以使用 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_%dn", time(NULL));
for (int i = 0; i <= 3; i++)
{
printf("Parent %dn", i);
sleep(1);
}
printf("0n");
printf("Cnt_Finished_at_%dn", time(NULL));
}
else 
{
// Child - Terminated by 0
int dp = dup2(fd[0], 0);
printf("Trm_Started_at_%dn", time(NULL));
char buffer[100];
scanf("%s", buffer);
printf("%sn", buffer);
int i; 
while (scanf("Parent %d", &i) && i)
printf("Recieved: %dn", i);
scanf("%s", buffer);
printf("%sn", buffer);
printf("Trm_Finished_at_%dn", time(NULL));
}
}

输出:

Trm_Started_at_1578295974
Cnt_Started_at_1578295974
Parent
Trm_Finished_at_1578295978

根本问题是使用"scanf %s"来读取消息。回想一下,"%s"在遇到空格时将停止读取,并将空格放回缓冲区。

来自父级的初始消息是"Cnt_Started_at_1234"。此子进程将读取令牌,但会将尾随的""保留在缓冲区中。

接下来,父级将发送"父级 0"。孩子将尝试解析这是scanf("Parent %d", &i) && i)。这里有两个问题:

">
  • 父"中的"P"与初始消息中剩余的""不匹配
  • 当格式更新为跳过前导空格时,"i"的值将为零,这将导致while在读取"父级 0"后退出。

可能的解决方案:允许扫描跳过空格,并消除 i 上的条件

while (scanf(" Parent %d", &i) == 1 )
printf("Recieved: %dn", i);

这里的问题出在你的scanf语句上。按照 @dash-o 的建议,将其更改为处理空格。

另一个问题是,首先i = 0.您需要修改您的 while 以适应 0。

由于您只在while loop中评估i,因此您不会输入"i=0"的情况。

下面是修改后的程序和输出,另外,请添加各种检查函数/缓冲区溢出的返回值,只要你认为正确--

#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_%dn", time(NULL));
for (int i = 0; i <= 3; i++)
{
printf("Parent %dn", i);
sleep(1);
}
printf("0n");
printf("Cnt_Finished_at_%dn", time(NULL));
}
else
{
// Child - Terminated by 0
int dp = dup2(fd[0], 0);
printf("Trm_Started_at_%dn", time(NULL));
char buffer[100];
scanf("%s", buffer);
printf("%sn", buffer);
int i;
while (scanf(" Parent %d", &i) && i >= 0) // notice change here ...
printf("Recieved: %dn", i);
scanf("%s", buffer);
printf("%sn", buffer);
printf("Trm_Finished_at_%dn", 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

最新更新