Вопрос о записи в файл в программе Producer-Consumer - PullRequest
0 голосов
/ 13 января 2020

Я должен написать две отдельные программы, одна из которых является производителем, а вторая - потребителем (обе работают в отдельных терминалах). Я предоставляю аргумент для продюсера, который может быть текстом или одним символом. Затем производитель создает файл .txt, помещает в него один символ и закрывает его. Потребитель открывает этот файл, читает этот символ и печатает его на терминале, затем закрывает файл и удаляет его. Весь процесс повторяется. Если указанный аргумент включает *, например * или text*, он завершает обе программы, печатая * перед завершением. Я могу использовать только функции: open(), close(), read(), write(), unlink(). Ожидаемый результат выглядит следующим образом:

expected result

Я написал оба кода, это код производителя:

(я в курсе из-за того, что я излишне определил 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, а остальные будут вставлены в другие файлы. Разве это не l oop и добавление всего слова text в один файл? Нет заявления, гарантирующего, что файл будет содержать один символ, однако он содержит только один символ, и я не знаю почему.

Ответы [ 2 ]

2 голосов
/ 13 января 2020

В источнике, когда вы используете флаги O_CREAT и O_EXCL при открытии файла, вызов не будет выполнен, если файл уже существует. Таким образом, на первой итерации внешнего l oop (при условии, что файл не существует) файл создается и записывается первый символ. На следующей итерации вызов open завершается неудачно, поскольку файл существует, поэтому он находится во внутренней l oop до тех пор, пока файл существует.

В приемнике вызов open выполнен в oop, пока это не удастся. Это произойдет, когда производитель пишет и закрывает файл. Затем потребитель читает символ из файла и удаляет его. Когда потребитель удаляет файл, вызов open в производителе завершается успешно и записывает второй символ в файл.

Этот процесс повторяется до тех пор, пока производитель не прочитает символ * и не запишет его в файл, после которого производитель выходит. Затем, когда потребитель читает *, он также выходит.

2 голосов
/ 13 января 2020

Я ограничу свой ответ вашим единственным конкретным c вопросом:

как программа Producer не вставляет в файл более одного символа?

Вы делаете следующее в al oop:

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, поскольку эта комбинация флагов откроет файл , только если он еще не существует . После написания первого символа ваша программа будет работать бесконечно l oop (while (fdi < 0)), пытаясь открыть файл второй раз.

С страница руководства для open():

O_EXCL : убедитесь, что этот вызов создает файл: если этот флаг указан вместе с O_CREAT, а pathname уже существует, то open () завершится неудачей.

Итак, во-первых, вам не нужен флаг O_EXCL. Кроме этого, если вы хотите добавлять данные в файл, а не перезаписывать его содержимое каждый раз, вы должны добавить флаг O_APPEND, когда вы open() файл. На странице руководства:

O_APPEND : файл открывается в режиме добавления. Перед каждой записью (2) смещение файла помещается в конец файла, как будто с lseek (2). Изменение смещения файла и операция записи выполняются в виде одного атома c шаг.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...