Вызывает ли fwrite внутреннюю блокировку?

В Solaris, когда я подключил dbx к одному из работающих стеков, я обнаружил, что вызов fwrite ведет к __lll_lock_wait()?

По какому сценарию это произойдет? Пытается ли fwrite получить блокировку изнутри?


person Jay    schedule 10.09.2010    source источник


Ответы (1)


стандарты, которые я просматривал (C99 и POSIX), ничего не говорят о заблокированном или разблокированном вводе-выводе относительно fwrite.

В моей системе Linux не очень точное упоминание о блокировке на странице man:

   For non-locking counterparts, see unlocked_stdio(3).

и фактически есть функция fwrite_unlocked. Стандартными разблокированными функциями в POSIX являются только getc_unlocked(), getchar_unlocked(), putc_unlocked() и putchar_unlocked().

Моя интерпретация заключается в том, что, вероятно, весь буферизованный ввод-вывод в наборе man(3) заблокирован, и что у вас есть очень мало стандартизированных интерфейсов для разблокированного ввода-вывода.

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

person Jens Gustedt    schedule 10.09.2010
comment
Это нехорошо, потому что степень детализации блокировки только на уровне байтов. То есть, если вы одновременно записываете строки или двоичные данные из двух потоков в один и тот же файл, это может привести к случайному чередованию. На практике большинство реализаций будут оборачивать блокировку вокруг всей более крупной операции, но они не обязаны этого делать, и правильный код не может зависеть от них. Так что блокировка практически бесполезна. Он защищает от повреждения памяти, если несколько потоков одновременно используют один и тот же файл, но это уже было ошибкой. - person R.. GitHub STOP HELPING ICE; 10.09.2010
comment
@Р. с хорошей вещью я имел в виду для принципа, что блокировка есть вообще. Я до сих пор помню, что в IRIX (который на самом деле не был совместим с POSIX) параллельный поток выдавал все, полностью чередуясь, в общий выходной поток. Но вы правы, то, как это делается, может быть подвергнуто критике. - person Jens Gustedt; 10.09.2010
comment
POSIX достаточно точно описывает блокировку на flockfile справочной странице. Все функции stdio, кроме _unlocked, должны выполнять внутренние эквиваленты flockfile/funlockfile. - person jilles; 11.09.2010
comment
@jilles: верно, спасибо. Какая жалость, что они не ссылаются на это на fwrite странице. Также на странице для stdio.h теперь я вижу, что все это является дополнительной функцией в POSIX. - person Jens Gustedt; 11.09.2010
comment
@R..: Тот же файл или тот же FILE*? 2 совсем другие. Для одновременных операций записи() в один и тот же файл чередование, скорее всего, произойдет на уровне секторного буфера в ядре или в атомарных копиях в буферы VFS. Чередование в этой ситуации, я не думаю, будет происходить с гранулярностью char. - person Matt Joiner; 12.09.2010
comment
В MSVCRT все FILE* операции заблокированы. Варианты *_unlocked поставляются без замков. Просто чтобы уточнить, все блокировки stdio во всех реализациях предназначены для предотвращения повреждения внутренних компонентов FILE и не имеют ничего общего с тем, как ОС обрабатывает ввод-вывод. - person Matt Joiner; 12.09.2010
comment
@Matt: я имел в виду то же самое FILE *. См. POSIX, раздел 2.5 Стандартные потоки ввода-вывода: весь ввод происходит так, как если бы байты считывались последовательными вызовами fgetc(); весь вывод происходит так, как если бы байты записывались последовательными вызовами fputc(). Это делает очень ясным, что с точки зрения спецификации блокировка осуществляется побайтно, и нет никакой защиты от чередующегося вывода. - person R.. GitHub STOP HELPING ICE; 12.09.2010