[APUE] родитель и ребенок совместно использует то же файловое смещение после ветвления?

Я использовал CppUnit с VS2005 и Eclipse. Wiki очень полна (особенно, если Вы знакомы с JUnit).

5
задан csl 28 October 2009 в 09:25
поделиться

4 ответа

Что ж, я ошибался.

Итак, они сообщают смещение, но происходит что-то еще странное. Если бы они не разделяли смещение, вы бы получили вывод, который выглядел бы так:

this is a long long output from chredt

, потому что каждый начал бы писать со своего смещения 0 и продвигать символ за раз. Они не начнут конфликтовать о том, что записывать в файл, пока не дойдут до последнего слова предложения, которое в конечном итоге перемежается.

Итак, они разделяют смещение.

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

Если смещение не было общим, в результате вы получите ровно столько байтов в файле, сколько самая длинная из двух строк.

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

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

  1. процесс A считывает смещение в A.offset
  2. процесс B считывает смещение в B.offset
  3. процесс A записывает байт в A.offset
  4. процесс A устанавливает смещение = A.offset + 1
  5. процесс B записывает байт в B. смещение
  6. процесс A считывает смещение в A. смещение
  7. процесс B устанавливает смещение = B. смещение + 1
  8. процесс A записывает байт в A. смещение
  9. процесс A устанавливает смещение = A. смещение + 1
  10. процесс B считывает смещение в B. смещение
  11. процесс B записывает байт в B. смещение
  12. процесс B устанавливает смещение = B. смещение + 1

Примерно такой должна быть последовательность событий. . Как очень странно.

Существуют системные вызовы pread и pwrite, поэтому два процесса могут обновлять файл в определенной позиции, не гоняясь за тем, чье значение глобального смещения побеждает.

3
ответ дан 13 December 2019 в 22:10
поделиться

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

Из моей справочной страницы write (2): «Регулировка смещения файла и операция записи выполняются как элементарный шаг».

Итак, отсюда, вы можете быть уверены, что никакая запись от одного (родительского или дочернего) не будет записываться поверх другого. Вы также можете отметить, что если бы вы написали (2) сразу все предложение (за один вызов write (2)), гарантируется, что предложения будут записаны вместе, как единое целое.

На практике многие системы пишут файлы журналов таким образом. Многие связанные процессы (дочерние процессы одного и того же родителя) будут иметь дескриптор файла, который был открыт родителем. Пока каждый из них записывает целую строку за раз (с одним вызовом write (2)), файл журнала будет читать так, как вы этого хотите. Написание персонажа за раз не будет иметь таких же гарантий. Использование буферизации вывода (например, stdio) аналогичным образом снимает гарантии.

Написание персонажа за раз не будет иметь таких же гарантий. Использование буферизации вывода (например, stdio) аналогичным образом снимает гарантии.

Написание персонажа за раз не будет иметь таких же гарантий. Использование буферизации вывода (например, stdio) аналогичным образом снимает гарантии.

4
ответ дан 13 December 2019 в 22:10
поделиться

If I recall correctly from my OS class, forking does give the child it's own offset (though it starts at the same position as the parents), it just keeps the same open file table. Although, most of what I'm reading seems to state otherwise.

1
ответ дан 13 December 2019 в 22:10
поделиться

Ну, я скорректировал код для компиляции на обычном GCC / glibc, и вот пример вывода:

thhis isias a l long oulout futput frd
 parent

И я думаю, что это подтверждает идею о том, что позиция в файле является общей, а является объектом гонки, поэтому это так странно. Обратите внимание, что данные, которые я показал, содержат 47 символов. Это больше, чем 38 или 39 символов в одном сообщении, и меньше, чем 77 символов обоих сообщений вместе - единственный способ, которым я могу это увидеть, - это если процессы иногда гонятся за обновлением позиции файла - каждый из них записывает символ, каждый из них пытается увеличить позицию, но из-за гонка происходит только на одно приращение, и некоторые символы перезаписываются.

Подтверждающие доказательства: man 2 lseek в моей системе ясно говорит

Обратите внимание, что файловые дескрипторы, созданные dup (2) или fork (2) совместно использовать указатель текущей позиции файла, поэтому поиск таких файлов может быть предметом состязания.

1
ответ дан 13 December 2019 в 22:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: