Зачем отмечать аргумент функции как volatile - PullRequest
18 голосов
/ 20 февраля 2012

Я сейчас читаю код PostgreSql . Вот выдержка из менеджера буферов:

static void WaitIO(volatile BufferDesc *buf);
static bool StartBufferIO(volatile BufferDesc *buf, bool forInput);
static void TerminateBufferIO(volatile BufferDesc *buf, bool clear_dirty,

Я знаю, что ключевое слово volatile обычно используется для драйверов устройств и во встроенных системах. Есть объяснение ключевого слова.

Когда ключевое слово volatile используется в определении типа, оно указывает компилятору на то, как оно должно обрабатывать переменную. Прежде всего, это говорит компилятору, что значение переменной может измениться в любое время в результате действий, внешних по отношению к программе или текущей строки выполнения. ( Источник )

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

Ответы [ 5 ]

19 голосов
/ 20 февраля 2012

volatile BufferDesc *buf означает, что данные, на которые buf указывает на , являются изменчивыми, а указатель, содержащийся в buf, является изменчивым.(Это будет BufferDesc * volatile buf.)

На странице, на которую вы ссылаетесь :

С другой стороны, если у вас есть переменная-указатель, гдеадрес сам по себе был нестабильным, но память, на которую указывал, не была тогда у нас:

int * volatile x;

Обновление : Извините, я пропустил эту часть вашего вопроса:

Так почему же некоторые аргументы функции объявляются как volatile?

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

7 голосов
/ 20 февраля 2012

Я не ожидаю, что DMA изменит местоположение указателя.

Не местоположение, а, возможно, содержимое.И это именно то, о чем идет речь ...

1 голос
/ 20 февраля 2012

Реализация баз данных не зависит от буферов и кешей ОС при доступе к файлам. Они предпочитают реализовывать собственную кеш-систему и получают прямой доступ к файлу на физическом диске , из-за проблем с надежностью: данные ДОЛЖНЫ быть сброшены на физический диск. (Они используют опцию O_DIRECT для прямого доступа к физическому диску.)

Три функции, которые вы нам показываете, заставляют меня думать об асинхронной обработке данных, поступающих с диска. (StartBufferIO (), TerminationBufferIO () и т. Д.). Честно говоря, я не уверен, какова их цель, но основываясь на том, что я знаю о реализации баз данных и этих именах функций, я бы сказал, что содержимое буфера может быть изменено самим "диском" с данными из файла на диске. (или какое-либо другое устройство), и поэтому должно быть помечено как volatile .

Эта гипотеза дополняет вашу обычную интерпретацию того, для чего обычно используется ключевое слово volatile : драйверы устройств.

0 голосов
/ 20 февраля 2012

Одна вещь, которую компилятор обычно делает при оптимизации, это удаление мертвого кода, поэтому, если вы выполняете некоторые операции с переменной, которую она никогда не читает, и ее результат бесполезен, компилятор, вероятно, просто удалит ее, а также удалит остальные операции.это влияет на это.Такое поведение может быть очень раздражающим, когда вы отлаживаете код или выполняете какие-то тесты.Если вы объявляете переменную как volatile, вы предупреждаете компилятор о том, что она может использоваться внешними библиотеками или программами, среди других последствий, которые может иметь ключевое слово.Тогда он никогда не должен воспринимать его как мертвый код.

0 голосов
/ 20 февраля 2012

DMA - не единственная причина использовать «volatile». Это также полезно для многопоточных приложений и приложений с общей памятью, где другой поток может изменить память, на которую ссылается этот код. Я уверен, что PostgreSql является многопоточным, поэтому это вероятная причина, по которой здесь используется volatile.

...