2008-11-20 3 views
30

Я хочу разгрузить блок кода в моем основном процессе дочерним процессом, чтобы он запускался одновременно. Я также хочу иметь PID порожденного дочернего процесса, чтобы я мог контролировать и убивать его, если это необходимо.Как вы создаете дочерний процесс в Ruby?

ответ

24

Вы можете использовать метод ядра fork. Ниже приведен пример:

#!/usr/bin/env ruby 
puts "This is the master process." 

child_pid = fork do 
    puts "This is the child process" 
    exit 
end 

puts "The PID of the child process is #{child_pid}" 

Метод fork возвращает PID процесса он вилок и выполняет какой-либо код в блоке прошло. Как и обычные блоки Ruby, он сохраняет привязки родительского процесса.

Это хорошая идея, чтобы сделать разветвленный процесс exit.

+1

Одна вещь, которую следует помнить с помощью Ruby, заключается в том, что не все работает точно так же, как в Windows по сравнению с * nix. Иногда они полностью не реализованы в Windows, поэтому используйте свою собственную опасность. – Daemin 2008-11-22 17:33:33

+7

Этот вообще не работает в Windows – vava 2009-02-14 04:55:00

+6

@Vadim Я думаю, что это особенность, а не ошибка. – 2009-02-15 23:57:41

36

В дополнение к замечательному ответу Криса, не забудьте позвонить Process.wait от своего хозяина, чтобы пожинать ваш детский процесс, иначе вы оставите зомби позади.

Примера в соответствии с просьбой в комментариях:

pid = Process.fork do 
    puts "child, pid #{Process.pid} sleeping..." 
    sleep 5 
    puts "child exiting" 
end 

puts "parent, pid #{Process.pid}, waiting on child pid #{pid}" 
Process.wait 
puts "parent exiting" 
2

Если вы счастливы использовать темы, а не процессы, а затем что-то вроде этого может быть немного более масштабируемым больше, чем одна вилка:

def doit(x) 
    sleep(rand(10)) 
    puts "Done... #{x}" 
end 

thingstodo = ["a","b","c","d","e","f","g"] 
tasklist = [] 

# Set the threads going 

thingstodo.each { |thing| 
    task = Thread.new(thing) { |this| doit(this) } 
    tasklist << task 
} 

# Wait for the threads to finish 

tasklist.each { |task| 
    task.join 
} 

Ознакомьтесь с замечательными комментариями и топологией Джона Топли, касающимися модели исполнения Ruby и ее ограничений.


Просто отредактирован, чтобы исправить вопиющую ошибку (не присваивания к задаче), и следовать @ совет (Jason King) 's.

2

Хорошая альтернатива вилка/Exec/мицелий является POSIX отродье камень для Ruby 1.9: https://github.com/rtomayko/posix-spawn

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

Смежные вопросы