Требование: «Использование нескольких процессов для одновременной записи одного и того же файла и одновременного чтения из файла строка за строкой».
<?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 .