Только для файлов в одном каталоге.

Только для файлов в одном каталоге.

В Linux openatсистемный вызов может использоваться для создания файлов и проверки их существования. Говоря в терминах модели памяти C/C++, создание файла и проверка его существования создает отношение synchronizes-with. Мне нужно знать, являются ли все эти синхронизации последовательно согласованными друг с другом. (Я, конечно, надеюсь на это, но я нигде не видел, чтобы это было задокументировано.)

Например, даны процессы p1 и p2, а также пути A и B:

если p1 делает это: create(A), то create(B)

и p2 делает это: пытается открыть (B), затем пытается открыть (A)

и никакие другие процессы не мешают A или B, возможно ли, что p2 успешно откроет B, но не сможет найти A?

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

решение1

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

решение2

Только для файлов в одном каталоге.

Есть 6 правил:

  1. Доступ на чтение. Правила блокировки: вызывающий блокирует каталог, к которому мы обращаемся. Блокировка принимается общей.

  2. Создание объекта. Правила блокировки: те же, что и выше, но блокировка берется исключительно.

  3. Удаление объекта. Правила блокировки: вызывающий блокирует родителя, находит жертву, блокирует жертву и вызывает метод. Блокировки являются исключительными.

  4. rename()то естьнетcross-directory. Правила блокировки: вызывающий блокирует родительский объект и находит источник и цель. В случае обмена (с RENAME_EXCHANGEаргументом флагов) блокирует оба. В любом случае, если цель уже существует, блокируйте ее. Если источник не является каталогом, блокируйте его. Если нам нужно заблокировать оба объекта, блокируйте их в порядке указателя inode. Затем вызовите метод. Все блокировки являются исключительными. Примечание: мы могли бы обойтись блокировкой источника (и цели в случае обмена) совместно.

  5. Создание ссылки. Правила блокировки:

    • блокировка родителя

    • проверьте, что источник не является каталогом

    • источник блокировки

    • вызовите метод. Все блокировки являются исключительными.

  6. Переименование между каталогами. Самое сложное из всех. Правила блокировки:

    • заблокировать файловую систему

    • зафиксируйте родителей в порядке «сначала предки».

    • найти источник и цель.

    • если старый родитель равен или является потомком цели, произойдет сбой с -ENOTEMPTY

    • если новый родитель равен или является потомком источника, произойдет сбой с -ELOOP

    • Если это обмен, заблокируйте и источник, и цель.

    • Если цель существует, заблокируйте ее. Если источник не является каталогом, заблокируйте его. Если нам нужно заблокировать оба, сделайте это в порядке указателя inode.

    • вызовите метод. Все ->i_rwsemони берутся эксклюзивно. Опять же, мы могли бы обойтись блокировкой источника (и цели в случае обмена) совместно используемого.

Приведенные выше правила, очевидно, гарантируют, что все каталоги, которые будут прочитаны, изменены или удалены методом, будут заблокированы вызывающей стороной.

Блокировка обеспечивает линеаризуемость, поэтому операциив одном каталогеполностью упорядочены. Однако доступ на чтение (1), создание объекта (2) и удаление объекта (3) не требуют более широких блокировок, чем блокировка каталога, поэтому нет никаких гарантий относительно порядка операций каталога в разных каталогах; разные наблюдатели могут видеть линейные истории каталогов, перемежающиеся по-разному.

Связанный контент