过管道将父进程的标准输出作为子进程的标准输入,在子进程中使用输入函数,出现阻塞现象

我试图通过管道将父进程的标准输出作为子进程的标准输入,但是子进程并不能通过管道读取到数据?
代码:
int main(void)
{
int fd[2];
pid_t pid;

    if(pipe(fd) < 0) //创建管道
    {
            perror("pipe error");
            exit(-1);
    }

    if((pid = fork()) < 0)// 创建子进程
    {
            exit(-1);
    }
    else if(pid == 0)
    {
            //puts("child start");
            char buf[100] = {0};

            close(fd[1]);
            dup2(fd[0], 0);//将管道的读端,作为标准输入
            close(fd[0]);
        
            gets(buf);//从标准输入中读取数据,存放在buf,相当于从fd[0]读数据存放在buf中
            puts(buf);//打印读取的数据
            //puts("child end");
    }
    else
    {
            //puts("parent start");
            close(fd[0]);
            write(fd[1], "123", 4);//往管道的写端,写入数据
            wait(NULL);
    }

    return 0;

}

运行结果阻塞!在子进程gets(buf)处!有人知道这个问题吗?如果将注释的puts函数取消注释,则正常输出,感觉和缓冲区有关系。。