Принадлежит ли указатель положения файла индексу, а не дескриптору файла? - PullRequest
1 голос
/ 19 февраля 2020

Требование: «Использование нескольких процессов для одновременной записи одного и того же файла и одновременного чтения из файла строка за строкой».

<?php

// from PHP doc
// 1. In a+ mode, fseek() only affects the reading position, writes are always appended.
// 2. If handle was fopen()ed in append mode, fwrite()s are atomic 
// (unless the size of string exceeds the filesystem's block size, on some platforms, 
// and as long as the file is on a local filesystem). 
// That is, there is no need to flock() a resource before calling fwrite(); 
// all of the data will be written without interruption.

$fd = fopen('/tmp/mylog.log', 'a+');

function write($fd, $pid, $n = 100) {
    static $num = 0;

    for ($i = 0; $i < $n; $i++) {
        fwrite($fd, $pid . " " .$num++ . PHP_EOL);
        sleep(1);
    }
}


function read($fd) {
    $offset = 0;
    while (true) {
        fseek($fd, $offset);

        $line = fgets($fd);
        $offset += strlen($line);
        echo $line;
    }
}

$processes = 5;
for ($i = 0; $i < $processes; $i++) {
    $pid = pcntl_fork();
    if ($pid == -1) {
        exit('could not fork!');
    } else if ($pid > 0) {
        // parent
    } else {
        // child, 1 reader, 4 writers
        if ($i == 0) {
            echo "start reader...\n";
            read($fd);
        } else {
            echo "start writerr...\n";
            write($fd, posix_getpid());
        }
        exit;
    }
}

// parent
for ($i = 0; $i < $processes; $i++) {
    pcntl_wait($status);
}

Я понял, что дочерние процессы будут использовать индикатор положения файла, потому что они будут использовать тот же файловый дескриптор (fd), в котором fopen() -ed их родительским процессом. Поэтому я должен вызвать fseek() в процессе чтения, чтобы он мог читать из позиции свойства.

Однако, когда я пытаюсь повторно fopen() тот же файл из процесса чтения, я получаю новый fd, как и ожидалось, но мне все еще нужно вызвать fseek(), в противном случае процесс чтения не может ничего прочитать.

function read($fd) {
    $fd = fopen('/tmp/mylog.log', 'rb'); // a new fd
    while (true) {
        $line = fgets($fd);
        echo $line;
    }
}

Так что я думаю, что индикатор положения файла относится к inode, а не к fd .

...