c - 使用管道从文件发送数据时出现同步错误

标签 c pipe readfile

我已经完成了这段代码:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#define BUFFER_SIZE 255
#define PATH "./test.txt"

int main(int argc, char **argv)
{
    char read_msg[BUFFER_SIZE];
    FILE *fp;
    char buffer[BUFFER_SIZE];
    fp = fopen(PATH, "r");
    int fd[2];
    pid_t pid;
    if(pipe(fd) == -1){
        perror("Pipe failed");
        return 1;
    }

    pid=fork();
    if (pid==-1)
    {
        perror("Fork failed");
        return 1;
    }

    if (pid>0)
    {
        close(fd[0]);
        fgets(buffer, BUFFER_SIZE, (FILE*)fp);
        do{
            write(fd[1],buffer,strlen(buffer)+1); 
            //sleep(1);
        }while(fgets(buffer, BUFFER_SIZE, (FILE*)fp) != NULL);
    close(fd[1]);
    wait(NULL);
}else{
    close(fd[1]);
    while(read(fd[0], read_msg, BUFFER_SIZE) != 0){
    printf("Child had read: %s", read_msg);
    } 
    close(fd[0]);
    }
    return 0;
}

这段代码必须在父进程和子进程之间创建一个管道。 父进程必须读取文件并将每一行发送给子进程。 子进程打印接收到的行。

但是这段代码有一些错误。 如果我这样运行,我只会得到文件中的几行文本。 如果我使用注释的 sleep(1) 运行,我会得到文本的所有行。

谁能看到错误?

最佳答案

你有两个问题。

这里:

write(fd[1],buffer,strlen(buffer)+1);

您正在将终止空值写入文件。当您调用 read() 时,如果有多行可用,它会将它们全部读入您的缓冲区,但是当您随后调用 printf() 时,它只会打印到第一个终止空值,因此您永远不会在第一行之后的任何行中看到它们。添加您的 sleep() 调用可以防止在另一个进程有机会 read() 之前将多行写入文件,因此问题不会出现在那种情况。

解决方案:不要将终止空值写入您的文本文件。同时,您可以通过更改以下代码使您的代码更紧凑:

fgets(buffer, BUFFER_SIZE, (FILE*)fp);
do{
    write(fd[1],buffer,strlen(buffer)+1); 
}while(fgets(buffer, BUFFER_SIZE, (FILE*)fp) != NULL);

到:

while ( fgets(buffer, BUFFER_SIZE, fp) ) {
     write(fd[1], buffer, strlen(buffer));
}

其次,read() 不会为您终止您的字符串,因此当您实现此解决方案时,此调用:

read(fd[0], read_msg, BUFFER_SIZE)

不会以 null 终止 read_msg。解决方案是检查 read() 实际读取了多少字节,并在该字节后手动添加终止空值。请注意,您最多需要读取比缓冲区大小少一个字节的内容,以防您将其填满,因为您需要为终止空值留出空间。

其他评论:

  1. 您不检查 fopen() 是否成功,但您应该检查。 write()close() 也是一样。您在检查其他情况下的返回值方面做得很好。

  2. fgets(buffer, BUFFER_SIZE, (FILE*)fp) 中转换为 FILE * 没有效果,因为 fp已经是 FILE * 类型。它应该被省略。

关于c - 使用管道从文件发送数据时出现同步错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36320267/

相关文章:

c - GCC __func__ 被评估为空字符串

c++ - 强制 Eclipse 将 .c 文件视为 C++

c++ - 如何在 Objective-C 中验证 JSON Schema?

python - 从数据文件中更改列表中的值

c - Eclipse 调试 C

c - 多次 fork 离开僵尸和进程挂起后程序控制不返回

c - 通过 C 中的管道读取表情符号

c - 通过管道填充 execlp 的输出,然后将其打印到控制台

Java读取文本文件以获取特定格式的值

c - 在c中获取文件中每一行的值