возможность блокировки для нескольких процессов, одновременно записывающих свой журнал в файл - PullRequest
0 голосов
/ 08 ноября 2019

Я проследил некоторую ошибку использования fputs и fflush в многопроцессорной среде. Поэтому я кодировал простой код, как показано ниже:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "windows.h"
#define FILENAME "test.txt"

int main(int argc , char *argv[]) 
{ 
    FILE *file; 
    file = fopen(FILENAME , "a"); 

    char buf[10240 + 100];
    int pid = GetCurrentProcessId();
    char buf_pid[20];
    itoa(pid, buf_pid, 10);

    int ii = 0;
    while(ii < 10000)
    {
        time_t     now = time(0);
        struct tm  tstruct;
        char       tt[80];
        tstruct = *localtime(&now);
        strftime(tt, sizeof(tt), "%Y/%m/%d %X", &tstruct);

        strcpy(buf, tt); 
        strcpy(buf + strlen(tt), " ");
        strcpy(buf + strlen(tt) + 1, buf_pid);
        strcpy(buf + strlen(tt) + strlen(buf_pid), " ");

        int len = strlen(tt) + strlen(buf_pid) + 1;

        int a = rand()%10240;
        char temp;
        for(int i=0;i<a;i++)
        {
            temp = 'a' + rand()%25;
            memset(buf + len, temp, 1);
            len++;
        }
        buf[len++] = '\n';
        buf[len++] = 0;

        //Sleep(1);
        printf("%d %s %d %d\n", ii, tt, pid, a);
        fputs(buf, file);
        fflush(file);**

        ii++;
    }

И я запустил какой-то пакетный файл, как показано ниже:

start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe
start filewrite.exe

Затем результат показывается, как показано ниже, конечно.

2019/11/08 22:57:14 261 rjatydimofugclqurclqecdrhvqsuwbvntmryktdl..
2019/11/08 22:57:14 261 ixoqldswtmhmjxqedqkprngproxvfpeuagbsxexje..
2019/11/08 22:57:14 261 skrhmutgpnkpwopudobptikjrfogdeairwyglcrqe..
2019/11/08 22:57:14 261 sqytmhtrnqkrtnfigwgcvvacgklmcjxinhehaqish..
2019/11/08 22:57:14 261 pvdvsfksuonldbwstvgflwjpecfymtfdrsnxlqqod..
2019/11/08 22:57:14 261 oqatxghvkhhjyvgnlymcjapedmpdakuuphbxnuqtd..
2019/11/08 22:57:14 261 ufrjkikbwvlvjejhpnndyebmgfjbmwvldsrlephow..
..

Нет явного мьютекса, поэтому fputs и fflush не являются автоматическими. Я знаю, что fputs - записать текст в буфер файла с его дескриптором в ядре os, а fflush - сбросить буфер на диск. И хотя объектов синхронизации нет, порядок доступа к каждому буферу или коду сброса будет сохранен.

Возможно ли блокировка с помощью приведенного выше кода? Или если есть 2 файла, которые пишутся многими процессами, возможна ли блокировка?

Я нашел соответствующую хорошую статью, но я не уверен, что это действительно произошло. Требуется ли синхронизация / очистка перед записью в заблокированный файл из нескольких потоков / процессов в режиме fopen a +? fputs и fflush, процесс записи и буферизации

Спасибо!

1 Ответ

1 голос
/ 08 ноября 2019

В программе есть «скрытая» блокировка - когда код открывает файл журнала, он использует режим APPEND («a» для открытия). Это приведет к установке флага O_APPEND для системных вызовов open.

Цитирование из man open:

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

Флаг гарантирует выполнение каждой операции записи (которая выполняется всякий раз, когда printf выполняется для сброса строк вfile), будет атомарным и не будет смешан с выходом других процессов. Синхронизация и блокировка происходят в ядре операционной системы, никаких действий пользователя не требуется .

...