Как сделать системный вызов `write ()` в Linux незамедлительно эффективным? - PullRequest
2 голосов
/ 28 апреля 2019

Я пишу REPL (read-execute-print-loop) для C. Я стараюсь поддерживать заголовочный файл, чтобы я мог определять новые функции на основе предыдущих функций. Всякий раз, когда я определяю новую функцию, я получаю новый временный файл, подобный этому:

#include "/tmp/header.h"

int foo() {
    return func() * func();
}

А /tmp/header.h это как:

int func();
int foo();

, где func() - ранее определенная функция.

Так что мне нужно снова и снова звонить write() на header_fileno. Меня беспокоит то, возможно ли, что после того, как я позвонил write(header_fileno, buf, wrsize), содержимое buf будет сохранено в некотором буфере ядра вместо записи в фактический файл ? Потому что, если это произойдет, я не могу рассчитывать на заголовок, чтобы дать последние объявления. У меня такая же проблема, когда дело доходит до исходного файла. И если это произойдет, есть ли способ сделать его немедленно эффективным?

Ответы [ 2 ]

2 голосов
/ 29 апреля 2019

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

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

Сказав это, это не применяется, если вы используете функции stdio, которые могут буферизовать данные перед записью. Это также не гарантирует, что ваши данные не будут потеряны или повреждены в случае сбоя системы; если вам нужна эта гарантия, вы должны использовать fsync() или открыть файл с помощью O_SYNC.

0 голосов
/ 28 апреля 2019

Согласно справочной странице для Linux , нет никакой гарантии, что write сохранит ваши данные на диск. Используйте fsync (или закройте файл), чтобы записать записанные данные на диск. (lseek также может быть полезно, если вы хотите использовать только один дескриптор файла.)

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

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

...