Возможно ли использовать fork в современном C ++? - PullRequest
0 голосов
/ 02 декабря 2019

Традиционный C ++ был очень простым, и только библиотека, предназначенная для создания потоков (например, pthread), породила другие потоки.

Современный C ++ намного ближе к Java, так как многие функции основаны на потоках, с готовыми пулами потоковзапуск асинхронных заданий и т. д. Гораздо более вероятно, что некоторая библиотека, включая стандартную библиотеку, использует потоки для асинхронного вычисления некоторой функции или настраивает инфраструктуру для этого, даже если она не используется.

В этом контексте, всегда ли безопасно использовать функции с глобальным воздействием, такие как fork?

Ответы [ 2 ]

2 голосов
/ 02 декабря 2019

Чтобы добавить к ответу peteigel мой совет: если вы хотите получить ответвление, сделайте это очень рано, до того, как начнутся какие-либо другие потоки, кроме основного.

В общем, все, что вы можете делать в C, вы можете делать в C ++, поскольку C ++, особенно в Linux с расширениями clang или gcc, чертовски близок к идеальному надмножеству C. Конечно, когда естьхорошие переносимые API в std C ++, используйте их. Каноническим примером является предпочтение std :: thread перед pthreads C API.

Одно предостережение - pthread_cancel, которого следует избегать в C ++ из-за исключительных ситуаций. См., Например, pthread отменять вред на C ++ .

Вот еще одна ссылка, объясняющая проблему: pthread_cancel в деструкторе

В общем, очистка C ++обработка в целом проще и элегантнее, чем C, поскольку RAII является неотъемлемой частью культуры C ++, а в C нет деструкторов.

2 голосов
/ 02 декабря 2019

Ответ на этот вопрос, как и почти все остальное в C ++, звучит так: «это зависит».

Если предположить, что в программе есть другие потоки, и эти потоки синхронизируются друг с другом, вызывая fork опасно. Это связано с тем, что fork не ожидает, когда все потоки станут точкой синхронизации (то есть освобождение мьютекса) для разветвления процесса. В разветвленном процессе будет присутствовать только поток, вызвавший fork, а остальные будут прерваны, возможно, в середине критической секции. Это означает, что любая память, совместно используемая другими потоками, которая не была std::atomic<int> или подобной, является неопределенным состоянием.

Если ваш разветвленный процесс читает из этой памяти или действительно ожидает запуска других потоков, он, вероятно, не будет работать надежно. Однако большинство случаев использования fork фактически не имеют предварительных условий для состояния программы . Это потому, что наиболее распространенная вещь - это немедленный вызов execv или аналогичный, чтобы вызвать подпроцесс. В этом случае весь ваш процесс как бы «заменяется» каким-то новым процессом, и вся память вашего старого процесса отбрасывается.

tl; dr - вызов fork может быть небезопаснымв многопоточных программах. Иногда это безопасно;например, если еще не появилось ни одного потока, или evecv вызывается немедленно. Если вы используете fork для чего-то другого, рассмотрите возможность использования темы.

См. справочную страницу и этого полезного блога для подробностей. .

...