Pid1 = fork { sleep 5; exit 3 }
Pid2 = fork { sleep 2; exit 3 }
Process.wait # Возвращает pid2
Process.wait2 # Возвращает [pid1,768]
Чтобы дождаться завершения конкретного потомка, применяются методы waitpid
и waitpid2
.
pid3 = fork { sleep 5; exit 3 }
pid4 = fork { sleep 2; exit 3 }
Process.waitpid(pid4,Process::WNOHANG) # Возвращает pid4
Process.waitpid2(pid3, Process::WNOHANG) # Возвращает [pid3,768]
Если второй параметр не задан, то вызов может блокировать программу (если такого потомка не существует). Второй параметр можно с помощью ИЛИ объединить с флагом Process::WUNTRACED
, чтобы перехватывать остановленные процессы. Этот параметр системно зависим, поэкспериментируйте.
Метод exit!
немедленно завершает процесс (не вызывая зарегистрированных обработчиков). Если задан целочисленный аргумент, то он возвращается в качестве кода завершения; по умолчанию подразумевается значение 1 (не 0).
pid1 = fork { exit! } # Вернуть код завершения -1.
pid2 = fork { exit! 0 } # Вернуть код завершения 0.
Методы pid
и ppid
возвращают соответственно идентификатор текущего и родительского процессов.
proc1 = Process.pid
fork do
if Process.ppid == proc1
puts "proc1 - мой родитель" # Печатается это сообщение.
else
puts "Что происходит?"
end
end
Метод kill
служит для отправки процессу сигнала, как это понимается в UNIX. Первый параметр может быть целым числом, именем POSIX-сигнала с префиксом SIG или именем сигнала без префикса. Второй параметр — идентификатор процесса-получателя; если он равен нулю, подразумевается текущий процесс.
Process.kill(1,pid1) # Послать сигнал 1 процессу pid1.
Process.kill ("HUP",pid2) # Послать SIGHUP процессу pid2..
Process.kill("SIGHUP",pid2) # Послать SIGHUP процессу pid3.
Process.kill("SIGHUP",0) # Послать SIGHUP самому себе.
Для обработки сигналов применяется метод Kernel.trap
. Обычно он принимает номер или имя сигнала и подлежащий выполнению блок.
trap(1) { puts "Перехвачен сигнал 1" }
sleep 2
Process.kill(1,0) # Послать самому себе.
О применениях метода trap
в более сложных ситуациях читайте в документации по Ruby и UNIX.
В модуле Process
есть также методы для опроса и установки таких атрибутов процесса, как идентификатор пользователя, действующий идентификатор пользователя, приоритет и т.д. Дополнительную информацию вы отыщете в справочном руководстве по Ruby.
14.1.4. Стандартный ввод и вывод
В главе 10 мы видели, как работают методы IO.popen
и IO.pipe
, но существует еще небольшая библиотека, которая иногда бывает удобна.
В библиотеке Open3.rb
есть метод popen3
, который возвращает массив из трех объектов IO
. Они соответствуют стандартному вводу, стандартному выводу и стандартному выводу для ошибок того процесса, который был запущен методом popen3
. Вот пример:
require "open3"
filenames = %w[ file1 file2 this that another one_more ]
inp, out, err = Open3.popen3("xargs", "ls", "-l")
filenames.each { |f| inp.puts f } # Писать в stdin процесса.
inp.close # Закрывать обязательно!
output = out.readlines # Читать из stdout.
errout = err.readlines # Читать также из stderr.
puts "Послано #{filenames.size} строк входных данных."
puts "Получено #{output.size} строк из stdout"
puts "и #{errout.size} строк из stderr."
В этом искусственном примере мы выполняем команду ls -l
для каждого из заданных имен файлов и по отдельности перехватываем стандартный вывод и стандартный вывод для ошибок. Отметим, что вызов close
необходим, чтобы порожденный процесс увидел конец файла. Также отметим, что в библиотеке Open3 используется метод fork
, не реализованный на платформе Windows; для этой платформы придется пользоваться библиотекой win32-open3
(ее написали и поддерживают Дэниэль Бергер (Daniel Berger) и Парк Хисоб (Park Heesob)). См. также раздел 14.3.
14.2. Флаги и аргументы в командной строке
Слухи о кончине командной строки сильно преувеличены. Хоть мы и живем в век графических интерфейсов, ежедневно тысячи и тысячи программистов по тем или иным причинам обращаются к командным утилитам.
Мы уже говорили, что корнями своими Ruby уходит в UNIX. Но даже в Windows существует понятие командной строки, и, честно говоря, мы не думаем, что в обозримом будущем она исчезнет.
На этом уровне для управления работой программы применяются аргументы и флаги. О них мы и поговорим ниже.
14.2.1. Разбор флагов в командной строке
Для разбора командной строки чаще всего применяется библиотека getoptlong
(библиотека getopts.rb
, обладающая менее развитой функциональностью, считается устаревшей). Она понимает однобуквенные и длинные флаги и распознает двойной дефис ( --
) как признак конца флагов. В целом библиотека ведет себя так же, как соответствующие функции GNU.
Читать дальше
Конец ознакомительного отрывка
Купить книгу