【问题标题】:Problem in writing to an output file using pipes使用管道写入输出文件时出现问题
【发布时间】:2020-02-20 14:53:15
【问题描述】:

我正在编写一个关于使用 OS 工具进行传输层多路复用的 C 程序。有3个比特流,分别在file1file2file3。我依次从file1file2file3 中读取 10 位并将它们组合成一个帧并将其存储在文件multiplex 中。

鉴于,唯一的通信方式是您创建的管道。

请注意:我没有使用fwrite 函数,而是想用管道探索更多。

对应的代码是

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/wait.h>


int main()
{
        int fd[3][2], pid,i, ch_count=10, count, status,f;
        FILE *fp, *fp1;
        fp1=fopen("multiplex.txt", "w");
        char ch, inp[10];

        for(i=0;i<3;i++)
                pipe(fd[i]);

        for(i=0;i<3;i++)
        {
                pid=fork();
                if(pid==0)
                {
                        printf("Inside Child process \n");
                        f=fileno(fp1);
                        close(fd[i][0]);
                        dup2(fd[i][1],f);
                        if(i==0)
                                        fp=fopen("file1.txt","r");
                        else if(i==2)
                                        fp=fopen("file2.txt","r");
                        else
                                        fp=fopen("file3.txt", "r");
                        while(1)
                        {
                                count=0;
                                while(( ch = fgetc(fp) ) != EOF && count<=ch_count)
                                        inp[count++]=ch;
                                if(ch==EOF)
                                        exit(0);
                                printf("The string read is %s \n", inp);
                                write(fd[i][1], inp, 10);
                                sleep(3-i);
                        }
                        close(fd[i][1]);
                }
                else
                        printf("Parent process \n");
        }
        return 0;
}

问题是:

i) 我无法在multiplex 文件中写入任何内容。

ii) 我在打印inp 字符串时读取了外来字符。此外,读取的字符串不是按顺序读取的(即首先是 file1,其次是 file2,然后是 file3)。输出是:

The string read is s not goldAR^�q�@�      //from file 2
                                     �7�U 
The string read is l that glitR^�q�@�      //from file 2 again
                                     �7�U 
The string read is s over the R^�q�@�      //from file 1
                                     �7�U 
The string read is well that eR^�q�@�      //from file 3
                                     �7�U 
The string read is ers is not R^�q�@�      //from file 2
                                     �7�U 
The string read is oldAll thatR^�q�@�
                                     �7�U 
The string read is ds well.AllR^�q�@�
                                     �7�U 
The string read is glitters isR^�q�@�
                                     �7�U 
The string read is azy dogThe R^�q�@�
                                     �7�U 
The string read is not goldAllR^�q�@�

有什么问题?

编辑: file1的内容

The_quick_brown_fox_jumps_over_a_lazy_dog_The_quick_brown_fox_jumps_over_a_lazy_dog_`

file2的内容

The_quick_brown_fox_jumps_over_a_lazy_dog_The_quick_brown_fox_jumps_over_a_lazy_dog_

file3的内容

All's_well_that_ends_well_All's_well_that_ends_well_All's_well_that_ends_well_

【问题讨论】:

  • multiplex 文件中写入任何内容的代码在哪里?
  • dup2(fd[i][1],f); 所做的是:关闭文件描述符 f,然后创建一个具有相同编号 f 的新文件描述符,它是文件描述符 fd[i][1] 的副本。此后原始文件描述符 f 没有任何区别,因为它已关闭。
  • 不,f 现在包含 fd[i][1]。 linux.die.net/man/2/dup2
  • 我的建议是你首先从文件 1 中读取,其次是文件 2,然后是文件 3。您不需要子进程,也不需要管道......
  • 请在您的问题中显示文件file1.txt 等的内容以及预期的输出。这将使我们能够测试您的程序。流程执行的顺序不固定。如果您想强制执行某个顺序,例如来自文件 1、2、3、1、2、3 等的 10 个字符,您必须实现同步机制。如果要将 10 个字符的输入打印为字符串,则必须使数组 inp[10] 更大,并在读取输入字符后附加 '\0',然后再使用 printf("... %s \n", inp); 当您在 exit 上使用 EOF 时你扔掉inp中的所有数据。

标签: c file pipe fork ipc


【解决方案1】:

i) 我无法在多路复用文件中写入任何内容。

通过

        fp1=fopen("multiplex.txt", "w");
        /* ... */
                        f=fileno(fp1);
                        dup2(fd[i][1],f);

您将 fp1 与“multiplex.txt”(在子级内)解除关联。在子级中使用fp1 是有风险的/未定义的,因为FILE 通常是缓冲的,并且缓冲区位置的变化不能在进程之间共享。

您将不得不重新设计您的程序(在子进程中写入管道,在父进程中读取)以实现所需的功能。

ii) 我在打印 inp 字符串时读取了外来字符。

                                while(( ch = fgetc(fp) ) != EOF && count<=ch_count)
                                        inp[count++]=ch;
                                /* ... */
                                printf("The string read is %s \n", inp);

不会零终止它。在 printf 之前执行 inp[count] = '\0',或者使用

                                printf("The string read is %.*s \n", (int)count, inp);

【讨论】:

  • 为了有空间添加尾随'\0',数组大小必须增加到char inp[11];
猜你喜欢
  • 1970-01-01
  • 2016-08-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多