【问题标题】:Question about writing to a file in Producer-Consumer program关于Producer-Consumer程序写入文件的问题
【发布时间】:2020-04-30 07:51:58
【问题描述】:

我必须编写两个独立的程序,一个是生产者,第二个是消费者(都在不同的终端中运行)。我向 Producer 提供了一个参数,该参数可以是文本或单个字符。然后,生产者创建一个.txt 文件,将单个字符放入其中,然后将其关闭。消费者打开该文件,读取该字符并将其打印在终端上,然后关闭该文件并将其删除。整个过程不断重复。如果提供的参数包含*,例如*text*,它将完成这两个程序,在结束前打印*。我只能使用函数:open()close()read()write()unlink()。预期结果如下所示:

这两个代码我都写了,这是生产者代码:

(我知道我不必要地定义了SIZE并使用了它,请不要介意)

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 1

int main(int argc, char *argv[]){

    char buff;
    do{
        int fdi=-1;
        while(fdi<0){
            fdi=open("test.txt",O_WRONLY | O_CREAT | O_EXCL, 0666);
        }
        read(STDIN_FILENO,&buff,SIZE);     
        write(fdi,&buff,SIZE);
        close(fdi);
    }while(buff!='*');
    return 0;
}

这是消费者代码:

#include <string.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>

#define SIZE 1

int main(int argc, char *argv[]){

    char buff;
    do{
        int fdi=-1;
        while(fdi<0){
            fdi=open("test.txt",O_RDONLY | O_EXCL);
        }
        int rdin=read(fdi,&buff,SIZE);
        if(rdin>0){
        write(STDOUT_FILENO,&buff,SIZE);
        close(fdi);
        unlink("test.txt");
        }
        else{
        close(fdi);
        }
    }while(buff!='*');
    return 0;
}

我的问题是:Producer 程序如何在文件中插入多个字符?我的意思是,如果我只运行 Producer 程序,并提供参数text,它只会在文件中插入字母t,其余的将插入到其他文件中。它不应该循环并将整个text 单词添加到一个文件中吗?没有任何声明保证文件将包含一个字符,但它只包含一个字符,我不知道为什么。

【问题讨论】:

  • 你怎么知道text中的哪个t被写入了文件?
  • read(STDIN_FILENO,&amp;buff,SIZE); 中的SIZE 是什么?那会读多少个字符?
  • @ScottHunter 我只是在其他终端运行“cat test.txt”,然后运行“rm test.txt”,我可以看到文件“t->e->x-> 中的字母发生了变化t"
  • @DavidC.Rankin 它是 buff 的大小,我在帖子中写道,我知道我不必要地定义它并且可能只写 1(因为 char 大小为 1 字节)
  • #define 是个好东西,评论是为了回应“Producer 程序怎么不会在文件中插入一个以上的字符?”

标签: c linux file producer-consumer


【解决方案1】:

在生产者中,当您在打开文件时使用O_CREATO_EXCL 标志时,如果文件已经存在,则调用将失败。因此,在外循环的第一次迭代中(假设文件不存在),文件被创建并写入第一个字符。在下一次迭代中,open 调用失败,因为文件存在,所以只要文件存在,它就处于内部循环中。

在消费者中,open 调用在循环中完成,直到成功。这将在生产者写入并关闭文件时发生。消费者然后从文件中读取字符并将其删除。当消费者删除文件时,生产者中的open调用将成功,并将第二个字符写入文件。

然后重复此过程,直到生产者读取* 字符并将其写入文件,之后生产者退出。然后当消费者读取* 时,它也会退出。

【讨论】:

    【解决方案2】:

    我的回答仅限于您的唯一具体问题:

    Producer 程序如何在文件中插入多个字符?

    您正在循环执行以下操作:

    do{
        int fdi = -1;
        while (fdi < 0){
            // Open the file only if it does not exist, creating it.
            fdi = open("test.txt", O_WRONLY | O_CREAT | O_EXCL, 0666);
        }
    
        // Read 1 char from stdin.
        read(STDIN_FILENO, &buff, SIZE);     
    
        // Write that char to the beginning of the file.
        write(fdi, &buff, SIZE);
    
        // Close and truncate the file.
        close(fdi);
    } while(buff != '*');
    

    第一次打开文件时,它也会被创建。从第二次开始,标志O_CREAT | O_EXCL 的组合将使open() 失败并出现错误EEXIST,因为这种标志组合将打开文件仅当它不存在时。写入第一个字符后,您的程序将无限循环 (while (fdi &lt; 0)) 尝试再次打开文件。

    来自the manual page for open()

    O_EXCL:确保此调用创建文件:如果此标志与 O_CREAT 和路径名一起指定 已经存在,那么 open() 会失败。

    所以,首先,您不需要O_EXCL 标志。除此之外,如果您想将数据附加到文件而不是每次都覆盖其内容,则应在 open() 文件时添加 O_APPEND 标志。从手册页:

    O_APPEND:文件以追加模式打开。在每次 write(2) 之前,文件偏移量位于文件末尾, 就像使用 lseek(2) 一样。文件偏移量的修改和写操作作为一个单一的执行 原子步骤。

    【讨论】:

    • 我已经运行了 Producer 代码并提供了“hello”作为参数,而 test.txt 的内容只是 'h'。我没有对代码进行任何更改。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-02
    • 1970-01-01
    • 2016-01-21
    相关资源
    最近更新 更多