الفرق بين المراجعتين ل"Ruby/Kernel/select"

من موسوعة حسوب
< Ruby‏ | Kernel
اذهب إلى التنقل اذهب إلى البحث
(أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: التابع <code>select‎</code> الخاص بالصنف <code>Kernel</code> في روبي}}</noinclude> تصنيف: Ruby تصني...')
 
(تدقيق.)
 
(مراجعتان متوسطتان بواسطة مستخدم واحد آخر غير معروضتين)
سطر 3: سطر 3:
 
[[تصنيف: Ruby Method]]
 
[[تصنيف: Ruby Method]]
 
[[تصنيف: Ruby Kernel]]
 
[[تصنيف: Ruby Kernel]]
يستدعي select(2). ويقوم بمراقبة المصفوفة المعطاة المكونة من كائنات <code>IO</code>، وينتظر حتى يكون أحد كائنات <code>IO</code> جاهزًا للقراءة ، وجاهزا للكتابة، ويكون لها استثناءات معلقة (pending exceptions) على التوالي، ثم يعيد مصفوفة تحتوي على مصفوفات مكونة من تلك كائنات <code>IO</code> السابقة. ستُعاد القيمة <code>nil</code> إذا تم إعطاء قيمة للوسيط الاختياري timeout، ولم يكن هناك أي كائن <code>IO</code> جاهزًا خلال timeout ثانية.
+
يستدعي التابع <code>select</code> دالة النظام <code>select(2)</code>‎، إذ يعمل على مراقبة المصفوفات الكائنات <code>[[Ruby/IO|IO]]</code> المعطاة، وينتظر حتى يصبح أحد تلك الكائنات أو أكثر جاهزًا للقراءة، وجاهزًا للكتابة، ومالكًا لاستثناءات معلقة (pending exceptions) على التوالي، ثم يعيد مصفوفة تحتوي على مصفوفات مكونة من الكائنات [[Ruby/IO|<code>IO</code>]] السابقة. سيعيد التابع القيمة <code>nil</code> إذا تم إعطاء قيمة للمهلة الزمنية <code>timeout</code>، ولم يكن هناك أي كائن جاهز خلال هذه الفترة.
تراقب <code>IO.select</code> المخزن المؤقت (buffer) لكائنات <code>IO</code> لاختبار قابليتها للقراءة. إذا لم يكن المخزن المؤقت <code>IO</code> فارغًا، فسيقوم <code>IO.select</code> على الفور بالابلاغ عن جاهزية القراءة. هذا المراقبة لا تشمل إلا <code>IO</code> كائنا. ولا تحدث للكائنات شبيهة IO مثل OpenSSL :: SSL :: SSLSocket.
 
أفضل طريقة لاستخدام <code>IO.select</code> هي باستدعائها بعد توابع غير مُعطّلة (nonblocking methods) مثل <code>read_nonblock</code> و <code>write_nonblock</code> ، وغيرهما. تطلق التوابع استثناء، والذي يُوسّع بواسطة <code>IO::WaitReadable</code> أو <code>IO::WaitWritable</code>. تقوم الوحدات (modules) بالابلاغ عن كيف ينبغي للمُستدعي (caller) الانتظار مع <code>IO.select</code>. في حال إطلاق <code>IO::WaitReadable</code> ، فسيكون على المُستدعي أن ينتظر لأجل القراءة. وفي حال إطلاق <code>IO::WaitWritable</code>، فيجب على المُستدعي أن ينتظر لأجل الكتابة.
 
لذلك، يمكن محاكاة حظر القراءة (<code>readpartial</code>) باستخدام <code>read_nonblock</code> و <code>IO.select</code> على النحو التالي:
 
  
على نحو خاص، يُفضل الجمع بين التوابع غير المُعطلة و <code>IO.select</code> للكائنات من صنف <code>IO</code>، مثل <code>OpenSSL::SSL::SSLSocket</code>. لديها طريقة <code>to_io</code> لإرجاع الكائن <code>IO</code> الأساسي. يستدعي <code>IO.select</code> التابع <code>to_io</code> لأجل الحصول على واصف الملف (file descriptor) المُنتظر.
+
يراقب التابع <code>[[Ruby/IO/select|IO.select]]</code> المخزن المؤقت (buffer) للكائنات [[Ruby/IO|<code>IO</code>]] لاختبار قابليتها للقراءة. إذا لم يكن المخزن المؤقت [[Ruby/IO|<code>IO</code>]] فارغًا، فسيُبلغ التابع <code>IO.select</code> مباشرةً عن جاهزية الكائن للقراءة. هذه المراقبة لا تشمل إلا الكائنات [[Ruby/IO|<code>IO</code>]]، ولا تُطبَّق على الكائنات الشبيهة للكائنات [[Ruby/IO|<code>IO</code>]] مثل<code>OpenSSL::SSL::SSLSocket</code>.
هذا يعني أن الإبلاغ عن قابلية القراءة من طرف <code>IO.select</code> لا تعني إمكانية القراءة من الكائن <code>OpenSSL::SSL::SSLSocket</code>.
 
وعلى الأرجح أن <code>OpenSSL::SSL::SSLSocket</code> تخزّن مؤقتا بعض البيانات. لا يرى <code>IO.select</code> المخزن المؤقت. لذلك يمكن للتابع <code>IO.select</code> أن يُعطل عندما لا يفعل <code>OpenSSL::SSL::SSLSocket#readpartial</code>.
 
لكن توجد حالات أكثر تعقيدًا.
 
SSL هو بروتوكول، وهو عبارة عن تسلسل السجلات. تتكون السجلات من عدة بتات. لذا، يرسل الجانب البعيد من SSL سجلًا جزئيًا، يقوم <code>IO.select</code> بالابلاغ عن إمكانية القراءة، ولكن لا يمكن لـ <code>OpenSSL::SSL::SSLSocket</code> فك التشفير البايت، فيقوم <code>OpenSSL::SSL::SSLSocket#readpartial</code> بالتعطيل.
 
يمكن أيضًا للجانب البعيد أن يطلب إعادة التفاوض حول SSL، والذي سيُجبر محرك SSL المحلي على كتابة بعض البيانات. هذا يعني أنّ <code>OpenSSL::SSL::SSLSocket#readpartial</code> قد ينفذ نظام الاستدعاء <code>write</code> ويمكنه الحجب. في مثل هذه الحالة، يطلق <code>OpenSSL::SSL::SSLSocket#read_nonblock</code> الاستثناء <code>IO::WaitWritable</code> بدلاً من التعطيل. لذلك، سيكون على المتصل الانتظار إلى حين جاهزية الكتابة كما هو مذكور أعلاه.
 
الجمع بين التوابع غير المُعطلة و <code>IO.select</code> مفيد أيضًا للمجاري (streams) مثل tty ، والقنوات pipe socket عندما تقوم عدة عمليات بالقراءة من مجرى معيّن.
 
وأخيراً، لا يمكن لمطوري نواة لينكس (Linux kernel developers) أنّ قابلية القراءة select(2) تعني قابلية القراءة لـ read(2) حتى ولو في نفس العملية. انظر توثيق select(2) في نظام جنو / لينكس.
 
استدعاء <code>IO.select</code> قبل <code>IO#readpartial</code> يعمل بشكل جيد كالمعتاد. لكنه ليست الطريقة الأفضل لاستخدام <code>IO.select</code>.
 
لا تُظهر قابلية الكتابة المُبلغ عنها من طرف select (2) عن عدد البايتات القابلة للكتابة. يتجمّد التابع <code>IO#write</code> إلى أن حين كتابة السلسلة النصية المعطاة كاملة. لذلك ، يمكن أن يُعطل <code>IO#write(two or more bytes)</code> بعد الابلاغ عن قابلية الكتابة من قبل <code>IO.select</code>. لتجنب التعطيل، لا بد من <code>IO#write_nonblock</code>.
 
يمكن محاكاة تعطيل الكتابة (<code>write</code>) باستخدام <code>write_nonblock</code> و <code>IO.select</code> كما يلي: يجب أن يتم حفظ <code>IO::WaitReadable</code> لأجل إعادة التفاوض SSL في <code>OpenSSL::SSL::SSLSocket</code>.
 
  
Parameters<code></code> <code></code>
+
أفضل طريقة لاستخدام التابع [[Ruby/IO/select|<code>IO.select</code>]] هو استدعاؤه عقِب استدعاء التوابع غير الحاجزة (nonblocking methods) مثل <code>[[Ruby/IO/read nonblock|read_nonblock]]</code> و <code>[[Ruby/IO/write nonblock|write_nonblock]]</code> وغيرهما. تطلق التوابع استثناءً يُوسَّع بواسطة <code>IO::WaitReadable</code> أو <code>IO::WaitWritable</code>. تبلِّغ الوحدات (modules) عن كيف ينبغي للمُستدعي (caller) الانتظار مع التابع <code>[[Ruby/IO/select|IO.select]]</code>. في حال إطلاق <code>IO::WaitReadable</code>، فسيكون على المُستدعي أن ينتظر لأجل القراءة؛ وفي حال إطلاق <code>IO::WaitWritable</code>، فيجب على المُستدعي أن ينتظر لأجل الكتابة.
read_array مصفوفة من كائنات <code>IO</code> التي تنتظر إلى حين جاهزية القراءة. write_array مصفوفة من كائنات <code>IO</code>، والتي تنتظر حتى جاهزية الكتابة error_array مصفوفة من كائنات <code>IO</code> التي تنتظر الاستثناءات timeout قيمة عددية بالثواني
 
Example<code></code> <code></code>
 
  
الناتج:
+
لذلك، يمكن محاكاة حظر القراءة (<code>[[Ruby/IO/readpartial|readpartial]]</code>) باستخدام التابع [[Ruby/IO/read nonblock|<code>read_nonblock</code>]] والتابع <code>[[Ruby/IO/select|IO.select]]</code> على النحو التالي:<syntaxhighlight lang="ruby">begin
 +
  result = io_like.read_nonblock(maxlen)
 +
rescue IO::WaitReadable
 +
  IO.select([io_like])
 +
  retry
 +
rescue IO::WaitWritable
 +
  IO.select(nil, [io_like])
 +
  retry
 +
end</syntaxhighlight>عمومًا، يُفضل الجمع بين التوابع غير الحاجزة والتابع [[Ruby/IO/select|<code>IO.select</code>]] بالنسبة للكائنات الشبيهة بالكائن [[Ruby/IO|<code>IO</code>]]، مثل <code>OpenSSL::SSL::SSLSocket</code>، إذ يعيد تابعها <code>to_io</code> الكائن [[Ruby/IO|<code>IO</code>]] الأساسي. كما يستدعي [[Ruby/IO/select|<code>IO.select</code>]] التابع <code>to_io</code> لأجل الحصول على واصف الملف (file descriptor) المُنتظر.
 +
 
 +
هذا يعني أنَّ الإبلاغ عن قابلية القراءة من طرف [[Ruby/IO/select|<code>IO.select</code>]] لا تعني إمكانية القراءة من الكائن <code>OpenSSL::SSL::SSLSocket</code>.
 +
 
 +
على الأرجح أنّ <code>OpenSSL::SSL::SSLSocket</code> يخزّن مؤقتًا بعض البيانات. لكن لا يرى [[Ruby/IO/select|<code>IO.select</code>]] المخزن المؤقت (buffer)، لذلك يمكنه أن يُعطل (block) عندما لا يفعل <code>OpenSSL::SSL::SSLSocket.readpartial</code>. على أي حال، توجد حالات أكثر تعقيدًا.
 +
 
 +
البروتوكول SSL هو عبارة عن تسلسل للسجلات (sequence of records). تتكون السجلات من عدة بايتات. لذا، يرسل الجانب البعيد من SSL سجلًا جزئيًا، ويبلِّغ التابع <code>IO.select</code> عن إمكانية القراءة، ولكن لا يمكن للكائن <code>OpenSSL::SSL::SSLSocket</code> فك تشفير البايتات، فيقوم <code>OpenSSL::SSL::SSLSocket.readpartial</code> بالتعطيل.
 +
 
 +
يمكن أيضًا للجانب البعيد أن يرسل طلب SSL لإعادة تفاوض أمني، والذي سيُجبر محرك SSL المحلي على كتابة بعض البيانات. هذا يعني أنّ <code>OpenSSL::SSL::SSLSocket.readpartial</code> قد يستدعي دالة النظام <code>write</code>، ويمكنه التعطيل. في مثل هذه الحالة، يُطلق <code>OpenSSL::SSL::SSLSocket.read_nonblock</code> الاستثناء <code>IO::WaitWritable</code>، بدلاً من التعطيل. لذلك، سيكون على المتصل الانتظار إلى حين جاهزية الكتابة كما هو مذكور أعلاه.
 +
 
 +
الجمع بين التوابع غير الحاجزة والتابع <code>IO.select</code> مفيد أيضًا للمجاري (streams) مثل <code>tty</code>، ومقابس الأنابيب (pipe socket)، عندما تقرأ عدة عمليات من مجرى معيّن.
 +
 
 +
وأخيرًا، لا يمكن لمطوري نواة لينكس أن يكونوا على يقين بأنّ قابلية القراءة للدالة <code>select(2)‎</code> تعني قابلية القراءة للدالة <code>read(2)</code>‎ عندما تتبعها حتى ولو في نفس العملية. انظر توثيق الدالة<code>select(2)</code> ‎ في أنظمة لينكس.
 +
 
 +
استدعاء <code>IO.select</code> قبل <code>IO.readpartial</code> يعمل بشكل جيد كالمعتاد، لكنه ليس الطريقة المثلى لاستخدام <code>IO.select</code>.
 +
 
 +
لا تُظهر قابلية الكتابة المُبلَّغ عنها من طرف الدالة <code>select(2)‎</code> عدد البايتات القابلة للكتابة. يُحجَب التابع <code>IO.write</code> إلى حين كتابة السلسلة النصية المعطاة كاملة. لذلك، يمكن أن يحجز <code>[[Ruby/IO/write|IO.write(two or more bytes)‎]]</code> بعد الابلاغ عن قابلية الكتابة من قبل <code>[[Ruby/IO/select|IO.select]]</code>. لتجنب الحجب، لا بد من استخدام <code>[[Ruby/IO/write nonblock|IO.write_nonblock]]</code>.
 +
 
 +
يمكن محاكاة تعطيل الكتابة (<code>write</code>) باستخدام <code>[[Ruby/IO/write nonblock|write_nonblock]]</code> و [[Ruby/IO/select|<code>IO.select</code>]] كما يلي: يجب أن يتم حفظ <code>IO::WaitReadable</code> لأجل إعادة التفاوض الأمني للبروتوكول SSL في الكائن <code>OpenSSL::SSL::SSLSocket</code>.<syntaxhighlight lang="ruby">while 0 < string.bytesize
 +
  begin
 +
    written = io_like.write_nonblock(string)
 +
  rescue IO::WaitReadable
 +
    IO.select([io_like])
 +
    retry
 +
  rescue IO::WaitWritable
 +
    IO.select(nil, [io_like])
 +
    retry
 +
  end
 +
  string = string.byteslice(written..-1)
 +
end</syntaxhighlight>
 
==البنية العامة==
 
==البنية العامة==
 
<syntaxhighlight lang="ruby">select(read_array [, write_array [, error_array [, timeout]]]) → array or nil‎</syntaxhighlight>
 
<syntaxhighlight lang="ruby">select(read_array [, write_array [, error_array [, timeout]]]) → array or nil‎</syntaxhighlight>
 
==المعاملات==
 
==المعاملات==
 
===<code>read_array‎</code>===
 
===<code>read_array‎</code>===
 
+
مصفوفةٌ من الكائنات <code>[[Ruby/IO|IO]]</code> التي تنتظر إلى حين جاهزيتها (واحد أو أكثر منها) للقراءة.
 
===<code>write_array‎</code>===
 
===<code>write_array‎</code>===
 
+
مصفوفة من الكائنات [[Ruby/IO|<code>IO</code>]]، والتي تنتظر حتى جاهزيتها (واحد أو أكثر منها) للكتابة.
 
===<code>error_array‎</code>===
 
===<code>error_array‎</code>===
 
+
مصفوفة من الكائنات [[Ruby/IO|<code>IO</code>]] التي تنتظر الاستثناءات.
 
===<code>timeout‎</code>===
 
===<code>timeout‎</code>===
 
+
قيمة عددية تمثل مهلة الانتظار بالثانية.
 
+
==القيمة المعادة==
==القيمة المُعادة==
+
تعاد مصفوفة تحتوي على مصفوفات مكونة من الكائنات [[Ruby/IO|<code>IO</code>]] المعطاة. إذا أعطي المعامل <code>timeout</code>  الاختياري، ولم يكن هناك أي كائن [[Ruby/IO|<code>IO</code>]] جاهز خلال <code>timeout</code> ثانية، فستُعاد القيمة <code>nil</code>.
 
 
 
==أمثلة==
 
==أمثلة==
مثال على استخدام التابع <code>select‎</code>:
+
مثال على استخدام التابع <code>select‎</code>:<syntaxhighlight lang="ruby">rp, wp = IO.pipe
<syntaxhighlight lang="ruby">begin
+
mesg = "ping "
  result = io_like.read_nonblock(maxlen)
+
100.times {
rescue IO::WaitReadable
+
  # IO.select follows IO#read.  Not the best way to use IO.select.
   IO.select([io_like])
+
   rs, ws, = IO.select([rp], [wp])
   retry
+
   if r = rs[0]
rescue IO::WaitWritable
+
    ret = r.read(5)
   IO.select(nil, [io_like])
+
    print ret
   retry
+
    case ret
end‎</syntaxhighlight>
+
    when /ping/
 +
      mesg = "pong\n"
 +
    when /pong/
 +
      mesg = "ping "
 +
    end
 +
  end
 +
   if w = ws[0]
 +
    w.write(mesg)
 +
   end
 +
}
 +
</syntaxhighlight>سنيتج عن تنفيذ هذه الشيفرة:<syntaxhighlight lang="text">ping pong
 +
ping pong
 +
ping pong
 +
(snipped)
 +
ping
 +
</syntaxhighlight>
 
==انظر أيضا==
 
==انظر أيضا==
* التابع <code>[[Ruby/Kernel/require_relative|require_relative]]</code>: عند استدعاء هذا التابع ستحاول روبي تحميل المكتبة المسماة في الوسيط المعطى string نسبة إلى مسار الملف المطلوب. إذا تعذر تحديد مسار الملف، سيُطلق خطأ <code>LoadError</code>. إذا تم تحميل ملف ستُعاد القيمة <code>true</code>، وإلا فستُعاد false على خلاف ذلك.
+
*التابع <code>[[Ruby/IO/write|write]]</code>: يكتب السلسلة النصية المعطاة في الملف ثم يعيد طول السلسلة النصية المكتوبة.
* التابع <code>[[Ruby/Kernel/set_trace_func|set_trace_func]]</code>: يجعل التابع set_trace_func الوسيط المعطى proc كمتعقب (handler for tracing)، أو يعطل التعقب إن كان الوسيط يساوي <code>nil</code>.
+
*التابع <code>[[Ruby/IO/write nonblock|write_nonblock]]</code>: يكتب السلسلة النصية المعطاة في <nowiki/>[[Ruby/IO|المجرى]] الذي استُدعي معه بعد تعيين قيمة الراية <code>O_NONBLOCK</code> الخاصة بواصف الملف (file descriptor) الأساسي ثم يعيد عدد البايتات المكتوبة.
 
+
*التابع [[Ruby/IO/read nonblock|<code>read_nonblock</code>]]: يقرأ عددًا محدَّدًا من البايتات من <nowiki/>[[Ruby/IO|المجرى]] الذي استُدعي معه بعد تعيين الراية <code>O_NONBLOCK</code> لواصف الملف (file descriptor) الأساسي ثم يعيدها.
 
==مصادر==
 
==مصادر==
*[http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-select قسم التابع select‎ في الصنف Kernel‎ في توثيق روبي الرسمي.]
+
*[http://ruby-doc.org/core-2.5.1/Kernel.html#method-i-select قسم التابع select‎ في الصنف Kernel‎ في توثيق روبي الرسمي.]

المراجعة الحالية بتاريخ 12:19، 16 نوفمبر 2018

يستدعي التابع select دالة النظام select(2)‎، إذ يعمل على مراقبة المصفوفات الكائنات IO المعطاة، وينتظر حتى يصبح أحد تلك الكائنات أو أكثر جاهزًا للقراءة، وجاهزًا للكتابة، ومالكًا لاستثناءات معلقة (pending exceptions) على التوالي، ثم يعيد مصفوفة تحتوي على مصفوفات مكونة من الكائنات IO السابقة. سيعيد التابع القيمة nil إذا تم إعطاء قيمة للمهلة الزمنية timeout، ولم يكن هناك أي كائن جاهز خلال هذه الفترة.

يراقب التابع IO.select المخزن المؤقت (buffer) للكائنات IO لاختبار قابليتها للقراءة. إذا لم يكن المخزن المؤقت IO فارغًا، فسيُبلغ التابع IO.select مباشرةً عن جاهزية الكائن للقراءة. هذه المراقبة لا تشمل إلا الكائنات IO، ولا تُطبَّق على الكائنات الشبيهة للكائنات IO مثلOpenSSL::SSL::SSLSocket.

أفضل طريقة لاستخدام التابع IO.select هو استدعاؤه عقِب استدعاء التوابع غير الحاجزة (nonblocking methods) مثل read_nonblock و write_nonblock وغيرهما. تطلق التوابع استثناءً يُوسَّع بواسطة IO::WaitReadable أو IO::WaitWritable. تبلِّغ الوحدات (modules) عن كيف ينبغي للمُستدعي (caller) الانتظار مع التابع IO.select. في حال إطلاق IO::WaitReadable، فسيكون على المُستدعي أن ينتظر لأجل القراءة؛ وفي حال إطلاق IO::WaitWritable، فيجب على المُستدعي أن ينتظر لأجل الكتابة.

لذلك، يمكن محاكاة حظر القراءة (readpartial) باستخدام التابع read_nonblock والتابع IO.select على النحو التالي:

begin
  result = io_like.read_nonblock(maxlen)
rescue IO::WaitReadable
  IO.select([io_like])
  retry
rescue IO::WaitWritable
  IO.select(nil, [io_like])
  retry
end

عمومًا، يُفضل الجمع بين التوابع غير الحاجزة والتابع IO.select بالنسبة للكائنات الشبيهة بالكائن IO، مثل OpenSSL::SSL::SSLSocket، إذ يعيد تابعها to_io الكائن IO الأساسي. كما يستدعي IO.select التابع to_io لأجل الحصول على واصف الملف (file descriptor) المُنتظر.

هذا يعني أنَّ الإبلاغ عن قابلية القراءة من طرف IO.select لا تعني إمكانية القراءة من الكائن OpenSSL::SSL::SSLSocket.

على الأرجح أنّ OpenSSL::SSL::SSLSocket يخزّن مؤقتًا بعض البيانات. لكن لا يرى IO.select المخزن المؤقت (buffer)، لذلك يمكنه أن يُعطل (block) عندما لا يفعل OpenSSL::SSL::SSLSocket.readpartial. على أي حال، توجد حالات أكثر تعقيدًا.

البروتوكول SSL هو عبارة عن تسلسل للسجلات (sequence of records). تتكون السجلات من عدة بايتات. لذا، يرسل الجانب البعيد من SSL سجلًا جزئيًا، ويبلِّغ التابع IO.select عن إمكانية القراءة، ولكن لا يمكن للكائن OpenSSL::SSL::SSLSocket فك تشفير البايتات، فيقوم OpenSSL::SSL::SSLSocket.readpartial بالتعطيل.

يمكن أيضًا للجانب البعيد أن يرسل طلب SSL لإعادة تفاوض أمني، والذي سيُجبر محرك SSL المحلي على كتابة بعض البيانات. هذا يعني أنّ OpenSSL::SSL::SSLSocket.readpartial قد يستدعي دالة النظام write، ويمكنه التعطيل. في مثل هذه الحالة، يُطلق OpenSSL::SSL::SSLSocket.read_nonblock الاستثناء IO::WaitWritable، بدلاً من التعطيل. لذلك، سيكون على المتصل الانتظار إلى حين جاهزية الكتابة كما هو مذكور أعلاه.

الجمع بين التوابع غير الحاجزة والتابع IO.select مفيد أيضًا للمجاري (streams) مثل tty، ومقابس الأنابيب (pipe socket)، عندما تقرأ عدة عمليات من مجرى معيّن.

وأخيرًا، لا يمكن لمطوري نواة لينكس أن يكونوا على يقين بأنّ قابلية القراءة للدالة select(2)‎ تعني قابلية القراءة للدالة read(2)‎ عندما تتبعها حتى ولو في نفس العملية. انظر توثيق الدالةselect(2) ‎ في أنظمة لينكس.

استدعاء IO.select قبل IO.readpartial يعمل بشكل جيد كالمعتاد، لكنه ليس الطريقة المثلى لاستخدام IO.select.

لا تُظهر قابلية الكتابة المُبلَّغ عنها من طرف الدالة select(2)‎ عدد البايتات القابلة للكتابة. يُحجَب التابع IO.write إلى حين كتابة السلسلة النصية المعطاة كاملة. لذلك، يمكن أن يحجز IO.write(two or more bytes)‎ بعد الابلاغ عن قابلية الكتابة من قبل IO.select. لتجنب الحجب، لا بد من استخدام IO.write_nonblock.

يمكن محاكاة تعطيل الكتابة (write) باستخدام write_nonblock و IO.select كما يلي: يجب أن يتم حفظ IO::WaitReadable لأجل إعادة التفاوض الأمني للبروتوكول SSL في الكائن OpenSSL::SSL::SSLSocket.

while 0 < string.bytesize
  begin
    written = io_like.write_nonblock(string)
  rescue IO::WaitReadable
    IO.select([io_like])
    retry
  rescue IO::WaitWritable
    IO.select(nil, [io_like])
    retry
  end
  string = string.byteslice(written..-1)
end

البنية العامة

select(read_array [, write_array [, error_array [, timeout]]])  array or nil

المعاملات

read_array‎

مصفوفةٌ من الكائنات IO التي تنتظر إلى حين جاهزيتها (واحد أو أكثر منها) للقراءة.

write_array‎

مصفوفة من الكائنات IO، والتي تنتظر حتى جاهزيتها (واحد أو أكثر منها) للكتابة.

error_array‎

مصفوفة من الكائنات IO التي تنتظر الاستثناءات.

timeout‎

قيمة عددية تمثل مهلة الانتظار بالثانية.

القيمة المعادة

تعاد مصفوفة تحتوي على مصفوفات مكونة من الكائنات IO المعطاة. إذا أعطي المعامل timeout الاختياري، ولم يكن هناك أي كائن IO جاهز خلال timeout ثانية، فستُعاد القيمة nil.

أمثلة

مثال على استخدام التابع select‎:

rp, wp = IO.pipe
mesg = "ping "
100.times {
  # IO.select follows IO#read.  Not the best way to use IO.select.
  rs, ws, = IO.select([rp], [wp])
  if r = rs[0]
    ret = r.read(5)
    print ret
    case ret
    when /ping/
      mesg = "pong\n"
    when /pong/
      mesg = "ping "
    end
  end
  if w = ws[0]
    w.write(mesg)
  end
}

سنيتج عن تنفيذ هذه الشيفرة:

ping pong
ping pong
ping pong
(snipped)
ping

انظر أيضا

  • التابع write: يكتب السلسلة النصية المعطاة في الملف ثم يعيد طول السلسلة النصية المكتوبة.
  • التابع write_nonblock: يكتب السلسلة النصية المعطاة في المجرى الذي استُدعي معه بعد تعيين قيمة الراية O_NONBLOCK الخاصة بواصف الملف (file descriptor) الأساسي ثم يعيد عدد البايتات المكتوبة.
  • التابع read_nonblock: يقرأ عددًا محدَّدًا من البايتات من المجرى الذي استُدعي معه بعد تعيين الراية O_NONBLOCK لواصف الملف (file descriptor) الأساسي ثم يعيدها.

مصادر