تتباطأ مكالمات fork(2)
نظرًا لأن العملية الأصلية تستخدم المزيد من الذاكرة بسبب الحاجة إلى نسخ جداول الصفحات. في العديد من الاستخدامات الشائعة لـ fork()، حيث تتبعها إحدى وظائف مجموعة exec لإنتاج عمليات فرعية ( Kernel#system
، IO::popen
، Process::spawn
، وما إلى ذلك)، من الممكن إزالة هذا الحمل باستخدام واجهات إنتاج العمليات الخاصة ( posix_spawn()
و vfork()
وما إلى ذلك)
تهدف مكتبة posix-spawn إلى تنفيذ مجموعة فرعية من واجهة Ruby 1.9 Process::spawn
بطريقة تستفيد من واجهات إنتاج العمليات السريعة عندما تكون متاحة وتوفر احتياطيات معقولة على الأنظمة التي لا تفعل ذلك.
Process::spawn
والإصدارات المحسنة من Kernel#system
و Kernel#`
وما إلى ذلك ضمن Ruby >= 1.8.7 (حاليًا التصوير بالرنين المغناطيسي فقط).POSIX::Spawn::Child
class لسيناريوهات IPC السريعة (لكن الصحيحة!) غير المتدفقة. توضح المعايير التالية الوقت اللازم لتقسيم/تنفيذ عملية فرعية لزيادة أحجام الذاكرة الموجودة على Linux 2.6 وMacOS X. تم إجراء الاختبارات باستخدام برنامج posix-spawn-benchmark
المضمن في الحزمة.
posix_spawn
أسرع من fork+exec
، ويتم تنفيذه في وقت ثابت عند استخدامه مع POSIX_SPAWN_USEVFORK
.
fork+exec
بطيء للغاية بالنسبة للعمليات الرئيسية الكبيرة.
posix_spawn
أسرع من fork+exec
، لكن لا يتأثر بحجم العملية الأصلية.
تشتمل هذه المكتبة على واجهتين متميزتين: POSIX::Spawn::spawn
، وهي واجهة نشر عملية ذات مستوى أدنى تعتمد على طريقة Ruby 1.9 Process::spawn
الجديدة، و POSIX::Spawn::Child
، وهي فئة ذات مستوى أعلى موجهة نحو النشر السهل العمليات ذات التعامل مع تيار الإدخال/الإخراج/الخطأ القياسي القائم على سلسلة بسيطة. الأول أكثر تنوعًا، بينما يتطلب الأخير تعليمات برمجية أقل بكثير لبعض السيناريوهات الشائعة.
تنفذ وحدة POSIX::Spawn
(بمساعدة ملحق C المصاحب) مجموعة فرعية من واجهة Ruby 1.9 Process::spawn، إلى حد كبير من خلال استخدام واجهات أنظمة IEEE Std 1003.1 posix_spawn(2)
. هذه مدعومة على نطاق واسع من قبل أنظمة تشغيل UNIX المختلفة.
في أبسط صوره، يمكن استخدام طريقة POSIX::Spawn::spawn
لتنفيذ عملية فرعية مشابهة لعملية Kernel#system
:
require 'posix/spawn'
pid = POSIX::Spawn::spawn('echo', 'hello world')
stat = Process::waitpid(pid)
ينفذ السطر الأول echo
باستخدام وسيطة واحدة ويعيد على الفور pid
العملية الجديدة. ينتظر السطر الثاني اكتمال العملية ويعيد كائن Process::Status
. لاحظ أن spawn
لا ينتظر انتهاء العملية من التنفيذ مثل system
ولا يحصد حالة خروج الطفل - يجب عليك الاتصال بـ Process::waitpid
(أو ما يعادله) وإلا ستصبح العملية زومبي.
أسلوب spawn
قادر على تنفيذ عدد كبير من العمليات الإضافية، بدءًا من إعداد بيئة العملية الجديدة، إلى تغيير دليل العمل التابع، إلى إعادة توجيه واصفات الملفات العشوائية.
راجع وثائق Ruby 1.9 Process::spawn
للحصول على التفاصيل وقسم STATUS
أدناه للحصول على حساب كامل لميزات Process::spawn
المتنوعة التي يدعمها POSIX::Spawn::spawn
.
system
و popen4
و `
بالإضافة إلى طريقة spawn
، يتم توفير تطبيقات متوافقة مع Ruby 1.9 لـ Kernel#system
و Kernel#`
في وحدة POSIX::Spawn
. يمكن استخدام طريقة popen4
لإنتاج عملية باستخدام كائنات stdin وstdout وstderr المُعاد توجيهها.
يمكن أيضًا دمج وحدة POSIX::Spawn
في الفئات والوحدات النمطية لتضمين spawn
وجميع الأساليب المساعدة في مساحة الاسم تلك:
require 'posix/spawn'
class YourGreatClass
include POSIX::Spawn
def speak(message)
pid = spawn('echo', message)
Process::waitpid(pid)
end
def calculate(expression)
pid, in, out, err = popen4('bc')
in.write(expression)
in.close
out.read
ensure
[in, out, err].each { |io| io.close if !io.closed? }
Process::waitpid(pid)
end
end
تتضمن فئة POSIX::Spawn::Child
منطقًا لتنفيذ العمليات الفرعية والقراءة/الكتابة من تدفقات الإدخال والإخراج والأخطاء القياسية. لقد تم تصميمه ليأخذ كل المدخلات في سلسلة واحدة ويوفر كل المخرجات كسلاسل فردية وبالتالي فهو غير مناسب تمامًا لتدفق كميات كبيرة من البيانات داخل وخارج الأوامر. وعلى هذا فإن له بعض الفوائد:
select(2)
) - يعالج جميع حالات تعليق الأنابيب بسبب تجاوز حدود PIPE_BUF
في تدفق واحد أو أكثر. POSIX::Spawn::Child
يأخذ وسيطات spawn
القياسية عند إنشاء مثيل لها، ويقوم بتشغيل العملية حتى الاكتمال بعد كتابة كل المدخلات وقراءة كل المخرجات:
>> require 'posix/spawn'
>> child = POSIX::Spawn::Child.new('git', '--help')
قم باسترجاع مخرجات العملية المكتوبة إلى stdout / stderr، أو افحص حالة خروج العملية:
>> child.out
=> "usage: git [--version] [--exec-path[=GIT_EXEC_PATH]]n ..."
>> child.err
=> ""
>> child.status
=> #<Process::Status: pid=80718,exited(0)>
استخدم خيار :input
لكتابة البيانات على stdin للعملية الجديدة مباشرة بعد النشر:
>> child = POSIX::Spawn::Child.new('bc', :input => '40 + 2')
>> child.out
"42n"
يمكن استخدام خيارات إضافية لتحديد الحد الأقصى لحجم الإخراج ( :max
) ووقت التنفيذ ( :timeout
) قبل إحباط العملية الفرعية. راجع مستندات POSIX::Spawn::Child
لمزيد من المعلومات.
POSIX::Spawn::Child.new
يولد العملية فورًا عند إنشاء مثيل لها. ونتيجة لذلك، إذا تمت مقاطعته بسبب استثناء (إما من الوصول إلى الحد الأقصى لحجم الإخراج، أو الحد الزمني، أو عامل آخر)، فلن يكون من الممكن الوصول إلى نتائج out
أو err
لأن المُنشئ لم يكتمل.
err
كنت ترغب في الحصول على بيانات out
وكانت البيانات متاحة عند مقاطعة العملية، فاستخدم النموذج البديل POSIX::Spawn::Child.build
لإنشاء الطفل دون نشر العملية على الفور. اتصل exec!
لتشغيل الأمر في مكان حيث يمكنك اكتشاف أي استثناءات:
>> child = POSIX::Spawn::Child.build('git', 'log', :max => 100)
>> begin
?> child.exec!
?> rescue POSIX::Spawn::MaximumOutputExceeded
?> # limit was reached
?> end
>> child.out
"commit fa54abe139fd045bf6dc1cc259c0f4c06a9285bbn..."
يرجى ملاحظة أنه عند ظهور الاستثناء MaximumOutputExceeded
، قد تكون البيانات out
الفعلية والبيانات err
أطول قليلاً من القيمة :max
بسبب التخزين المؤقت الداخلي.
تم تصميم طريقة POSIX::Spawn::spawn
لتكون متوافقة مع Process::spawn
قدر الإمكان. وهي الآن مجموعة فرعية متوافقة.
هذه الوسائط Process::spawn
مدعومة حاليًا لأي من Spawn::spawn
و Spawn::system
و Spawn::popen4
و Spawn::Child.new
:
env: hash
name => val : set the environment variable
name => nil : unset the environment variable
command...:
commandline : command line string which is passed to a shell
cmdname, arg1, ... : command name and one or more arguments (no shell)
[cmdname, argv0], arg1, ... : command name, argv[0] and zero or more arguments (no shell)
options: hash
clearing environment variables:
:unsetenv_others => true : clear environment variables except specified by env
:unsetenv_others => false : don't clear (default)
current directory:
:chdir => str : Not thread-safe when using posix_spawn (see below)
process group:
:pgroup => true or 0 : make a new process group
:pgroup => pgid : join to specified process group
:pgroup => nil : don't change the process group (default)
redirection:
key:
FD : single file descriptor in child process
[FD, FD, ...] : multiple file descriptor in child process
value:
FD : redirect to the file descriptor in parent process
:close : close the file descriptor in child process
string : redirect to file with open(string, "r" or "w")
[string] : redirect to file with open(string, File::RDONLY)
[string, open_mode] : redirect to file with open(string, open_mode, 0644)
[string, open_mode, perm] : redirect to file with open(string, open_mode, perm)
FD is one of follows
:in : the file descriptor 0 which is the standard input
:out : the file descriptor 1 which is the standard output
:err : the file descriptor 2 which is the standard error
integer : the file descriptor of specified the integer
io : the file descriptor specified as io.fileno
هذه الخيارات غير مدعومة حاليًا:
options: hash
resource limit: resourcename is core, cpu, data, etc. See Process.setrlimit.
:rlimit_resourcename => limit
:rlimit_resourcename => [cur_limit, max_limit]
umask:
:umask => int
redirection:
value:
[:child, FD] : redirect to the redirected file descriptor
file descriptor inheritance: close non-redirected non-standard fds (3, 4, 5, ...) or not
:close_others => false : inherit fds (default for system and exec)
:close_others => true : don't inherit (default for spawn and IO.popen)
خيار :chdir
المقدم من Posix::Spawn::Child وPosix::Spawn#spawn وPosix::Spawn#system وPosix::Spawn#popen4 ليس آمنًا لمؤشر الترابط لأن العمليات التي تم إنشاؤها باستخدام استدعاء النظام posix_spawn(2) ترث دليل العمل لعملية الاستدعاء. تعمل جوهرة posix-spawn على التغلب على هذا القيد في استدعاء النظام عن طريق تغيير دليل العمل الخاص بعملية الاستدعاء مباشرة قبل وبعد إنتاج العملية الفرعية.
حقوق الطبع والنشر (ج) لريان تومايكو وأمان جوبتا.
راجع ملف COPYING
لمزيد من المعلومات حول الترخيص وإعادة التوزيع.