Ответ 1
EDIT. Существует один распространенный вариант использования fork()
, который можно заменить на spawn()
- комбинацию fork()
- exec()
. Многие старые (и современные) UNIX-приложения, когда они хотят создать другой процесс, будут сначала вилкой, а затем сделать вызов exec
(exec
заменяет текущий процесс другим). Это действительно не нужно fork()
, поэтому его можно заменить на spawn()
. Итак, это:
if(!fork())
exec("dir")
end
можно заменить на:
Process.spawn("dir")
Если какой-либо из камней использует fork()
, как это, исправление легко. В противном случае это почти невозможно.
EDIT: причина, по которой реализация fork()
win32-process 'не работает, заключается в том, что (насколько я могу судить по документам) это в основном spawn()
, что вообще не является fork()
.
Нет, я не думаю, что это можно сделать. Как видите, Process.spawn
создает новый процесс с пустым состоянием по умолчанию и собственным кодом. Поэтому, хотя я могу сделать что-то вроде Process.spawn('dir')
, запустит новый, пустой процесс с запуском dir
, он не будет клонировать какое-либо из текущего состояния процесса. Это единственное соединение с вашей программой - это соединение родитель-ребенок.
Вы видите, fork()
- вызов очень низкого уровня. Например, в Linux, что fork()
в основном делает это: во-первых, создается новый процесс с точно клонированным регистром. Затем Linux делает ссылку "копирование на запись" на все страницы родительского процесса. Затем Linux клонирует некоторые другие флаги процесса. Очевидно, что все эти операции могут выполняться только ядром, а ядро Windows не имеет возможностей для этого (и не может быть исправлено).
Технически, только родные программы нуждаются в ОС для своего рода поддержки fork()
. Любой слой кода требует взаимодействия слоя над ним, чтобы сделать что-то вроде fork()
. Поэтому, в то время как родной код C нуждается в сотрудничестве ядра с fork, Ruby теоретически нуждается только в сотрудничестве с интерпретатором, чтобы сделать вилку. Однако интерпретатор Ruby не имеет функции моментального снимка/восстановления, которая была бы обязательно для реализации вилки. Из-за этого обычная вилка Ruby достигается путем разворачивания самого интерпретатора, а не программы Ruby.
Итак, если вы можете исправить интерпретатор Ruby, чтобы добавить функцию stop/start и snapshot/restore, вы можете это сделать, но в противном случае? Я так не думаю.
Итак, каковы ваши варианты? Это то, о чем я могу думать:
- Исправить интерпретатор Ruby
- Замените код, который использует
fork()
, чтобы использовать потоки или нереститься - Получить UNIX (я предлагаю этот)
- Использовать Cygwin
Изменить 1: Я бы не предложил использовать вилку Cygwin, поскольку она включает специальные таблицы процессов Cygwin, существует нет copy-on-write, что делает ее очень неэффективной. Кроме того, он включает в себя много прыжков назад и вперед и много копирования. Избегайте его, если это возможно. Кроме того, поскольку Windows не предоставляет возможности для копирования адресных пространств, вилки с большой вероятностью потерпят неудачу и будут довольно много времени (см. здесь).