我试图分叉一个进程,并将父级的 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