Два процесса пишут в одном файле - PullRequest
0 голосов
/ 10 апреля 2019

Я знаю, что это рецепт катастрофы.И я фактически заставил это работать, используя общие переменные.

Но это домашнее задание, и учитель определенно хочет, чтобы мы поместили много процессов, записывающих в один и тот же файл, используя разные файловые указатели.Я пытался весь день с небольшим успехом, но я просто не могу понять, почему это не удается.

Я подошел к проблеме следующим образом:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[])
{
    int status;
    int process_count = 0;

    do
    {
        int from = (n / np) * (process_count) + 1;
        int to = (n / np) * (process_count + 1);

        if (fork() == 0)
        {
            FILE *aux;
            aux = fopen("./parciais.txt", "w");
            fseek(aux, sizeof(int) * process_count, SEEK_SET);

            int sum = 0;
            int i = from;
            while (i <= to)
            {
                int square = i * i;
                sum += square;
                i++;
            }

            long int where_am_i = ftell(aux);
            printf("I am process %i writing %i on byte: %li\n", process_count, sum, where_am_i);

            fwrite(&sum, sizeof(int), 1, aux);
            fclose(aux);
            exit(1);
        }
        else
        {
            wait(&status);
            process_count++;
        }
    } while (process_count < np);

    FILE *aux;
    aux = fopen("./parciais.txt", "r");

    int sum;
    for (int i = 0; i <= np - 1; i++)
    {

        fseek(aux, sizeof(int) * i, SEEK_SET);
        long int where_am_i = ftell(aux);

        int read;
        fread(&read, sizeof(int), 1, aux);
        printf("I am reading %i at byte: %li\n", read, where_am_i);

        sum += read;
    }
}

Я ожидалвывод будет что-то вроде:

I am process 0 writing 98021 on byte: 0
I am process 1 writing 677369 on byte: 4
I am process 2 writing 1911310 on byte: 8
I am reading 98021 at byte: 0
I am reading 677369 at byte: 4
I am reading 1911310 at byte: 8

Но я получаю:

I am process 0 writing 98021 on byte: 0
I am process 1 writing 677369 on byte: 4
I am process 2 writing 1911310 on byte: 8
I am reading 0 at byte: 0
I am reading 0 at byte: 4
I am reading 1911310 at byte: 8

Это означает, что по какой-то причине записывается только последнее значение.

IЯ бился головой об стену из-за этого, и я просто не могу найти, где подвох ... Может кто-нибудь, пожалуйста, протяните мне руку?

Ответы [ 2 ]

1 голос
/ 11 апреля 2019

Как уже ответил @ B.Go, основная проблема в том, что вы открываете файл в режиме "w", который усекает его до нулевой длины, если он уже существует. Каждый дочерний процесс делает это, забивая содержание, написанное предыдущим.

Вы хотите эту комбинацию поведения для файла:

  • он создается, если он еще не существует (или, я думаю, вы этого хотите, по крайней мере)
  • он не усекается при открытии, если он действительно уже существует
  • Вы можете написать ему
  • записывает начало с текущим смещением файла, в отличие от автоматического перехода к текущему концу файла
  • файл является двоичным, не подлежит переводу символов или хвостовому усечению при записи в него

К сожалению, нет стандартного режима, который обеспечивает все это: различные режимы r требуют, чтобы файл уже существовал, режимы w усекают файл, если он уже существует, и режимы a направляют все записи в текущий конец файла, независимо от текущего смещения потока. Если вы можете предположить, что файл уже существует, то режим "r+b", который также может быть записан "rb+", имеет все требуемые характеристики, кроме создания файла, если он не существует:

    aux = fopen("./parciais.txt", "r+b");

Это также позволяет читать, но только то, что вы можете читать из файла, не означает, что вы должны это делать. Кроме того, в Linux и POSIX-совместимых системах нет различия между двоичными и текстовыми файлами, поэтому вы можете опустить b, если уверены, что ваша программа должна работать только в системах POSIX. То, что вы используете fork(), предполагает, что это условие может применяться к вам.

Если вы также должны предусмотреть создание файла, откройте его один раз в самом начале программы, используя любой из режимов w или a в зависимости от того, хотите ли вы обрезать файл, а затем немедленно закройте его снова:

FILE *aux = fopen("./parciais.txt", "a");
if (aux) {
    fclose(aux);
} else {
    // handle error ...
}
1 голос
/ 11 апреля 2019

Проблема связана с fopen("./parciais.txt", "w"):
"w": "Создает пустой файл для записи. Если файл с таким именем уже существует, его содержимое стирается, и файл считается новым пустымfile. "
Попробуйте вместо" a "!
(" Добавляет в файл. Операции записи, добавление данных в конец файла. Файл создается, если он не существует. ")

Как уже упоминалось в другом ответе, аргумента" а "также недостаточно.Файл должен быть создан один раз, следовательно, в основном процессе, а затем доступен в режиме «r + b» для правильной работы fseek!

...