О разветвлении процессов в Windows
2014-09-17 09:26 pmНекоторые люди не понимают, почему в Win32 API нет аналога системного вызова fork(2) из POSIX API. Ведь его можно реализовать на основе функции NtCreateProcess из NT Native API! В справочнике Гэри Нэббета даже есть соответствующий пример.
Это достаточно просто объяснить: разветвление процессов несовместимо с глобальными (межпроцессными) мьютексами. Если на момент разветвления мьютекс находился в заблокированном состоянии, тогда какой из двух процессов должен оказаться владельцем этой блокировки? И как уведомить о произошедшем событии lock elision библиотечный код, который не рассчитан на получение таких уведомлений?
В POSIX подсистеме Windows NT (MS Services for UNIX, также известной под торговой маркой Interix) есть fork, и следовательно нет глобальных мьютексов.
А в подсистеме Win32 есть глобальные мьютексы, а значит нет fork'а.
В "настоящих" POSIX-системах, таких как Linux и FreeBSD, есть и fork, и pthread-мьютексы, но природа этих мьютексов отличается от природы мьютексов Win32 — они процесс-локальны, примерно как критические секции в Win32. Таким образом, они могут пережить разветвление, не мешая друг другу в двух новых процессах.
Это достаточно просто объяснить: разветвление процессов несовместимо с глобальными (межпроцессными) мьютексами. Если на момент разветвления мьютекс находился в заблокированном состоянии, тогда какой из двух процессов должен оказаться владельцем этой блокировки? И как уведомить о произошедшем событии lock elision библиотечный код, который не рассчитан на получение таких уведомлений?
В POSIX подсистеме Windows NT (MS Services for UNIX, также известной под торговой маркой Interix) есть fork, и следовательно нет глобальных мьютексов.
А в подсистеме Win32 есть глобальные мьютексы, а значит нет fork'а.
В "настоящих" POSIX-системах, таких как Linux и FreeBSD, есть и fork, и pthread-мьютексы, но природа этих мьютексов отличается от природы мьютексов Win32 — они процесс-локальны, примерно как критические секции в Win32. Таким образом, они могут пережить разветвление, не мешая друг другу в двух новых процессах.
no subject
Date: 2014-09-18 05:38 am (UTC)no subject
Date: 2014-09-18 08:27 am (UTC)Для связи stdin/stdout/stderr дочернего процесса и в Windows, и в UNIX хорошо подходят anonymous pipes.
Межпотоковое взаимодействие в рамках одного процесса обычно предполагает блокировку вокруг общих ресурсов, для чего хорошо подходят критические секции Win32, или их аналоги - pthread_mutex (к ним тоже можно прикрутить ограниченную по количеству циклов спин-блокировку - pthread_mutex_setspinloops_np в FreeBSD или вручную написанный дополнительный код в Linux).
Межпотоковое взаимодействие в рамках одного процесса также может организовано на основе сообщений. Поскольку адресное пространство общее, достаточно передать другому потоку только некий указатель или номер слота. Механизм: kqueue + EVFILT_USER в FreeBSD, QueueUserAPC + alertable wait в Windows, или pipe в Linux (запись короткими блоками, напр. 8 байт, будет атомарной).
Для атипичных задач синхронизации, которые выходят за рамки передачи сообщений и защиты общих объектов, лучше ничего не выдумывать и очень внимательно читать теорию:
http://www.cs.ucr.edu/~kishore/papers/semaphores.pdf
Всё уже украдено до нас.