English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

التعامل مع الإشارات في Erlang

يحتاج البرمجة المتوازية في Erlang إلى اتباع المبادئ الأساسية أو العمليات التالية.

القائمة تتضمن المبادئ التالية:

piD = spawn(Fun)

إنشاء عملية جديدة لتقييم Fun. يعمل هذا العملية بشكل متوازي مع المُتصل.

مثال

-مودول(helloworld). 
-export([start/0]). 
start() ->
   spawn(fun() -> server("Hello") end). 
server(Message) ->
   io:fwrite("~p",[Message]).

上面程序的输出是-

输出

"Hello"

Pid ! Message

إرسال رسالة إلى العملية باستخدام معرف Pid. إن عملية الإرسال غير متزامنة. لن ينتظر المرسل، بل يستمر في ما يفعله. "!" يُدعى عميل الإرسال.

مثال على هذا -

مثال

-مودول(helloworld). 
-export([start/0]). 
start() -> 
   Pid = spawn(fun() -> server("Hello") end), 
   Pid ! {hello}. 
server(Message) ->
   io:fwrite("~p",[Message]).

Receive…end

استقبال الرسائل التي تم إرسالها إلى العملية. إنها تحتوي على الجملة التالية -

اللغة

استقبال
Pattern1 [when Guard1] ->
Expressions1;
Pattern2 [when Guard2] ->
Expressions2;
...
End

عند وصول الرسالة إلى هذا العملية، ستحاول النظام مطابقتها مع نموذج Pattern1 (قد يكون هناك Guard 1). إذا نجح، فإنه يقيّم Expressions1. إذا لم تطابق النموذج الأول، فإنه يحاول استخدام Pattern2، وهكذا. إذا لم تطابق أي نموذج، فإنه يحفظ الرسالة للمستقبلية معالجة، ثم ينتظر الرسالة التالية.

以下程序显示了使用全部3个命令的整个过程的示例。

مثال

-مودول(helloworld). 
-export([loop/0, start/0]). 
loop() ->
   استقبال 
      {rectangle, Width, Ht} -> 
         io:fwrite("Area of rectangle is ~p~n", [Width * Ht]), 
         loop(); 
      {circle, R} ->
      io:fwrite("Area of circle is ~p~n", [3.14159 * R * R]), 
      loop(); 
   Other ->
      io:fwrite("Unknown"), 
      loop(), 
   fin. 
start() ->
   Pid = spawn(fun() -> loop() end), 
   Pid ! {rectangle, 6, 10}.

关于上述程序,需要注意以下几点:

  • loop函数具有接收端循环。因此,当消息被发送时,它将被接收端循环处理。

  • 生成一个新进程,该进程将转到循环函数。

  • 通过 Pid! message 命令将消息发送到产生的进程。

上面程序的输出是-

输出

矩形的面积是60

最大进程数

并发地,重要的是确定系统上允许的最大进程数。然后,您应该能够了解系统上可以同时执行多少个进程。

让我们看一个示例,该示例如何确定系统上可以执行的最大进程数。

-مودول(helloworld). 
-export([max/1, start/0]). 
max(N) -> 
   Max = erlang:system_info(process_limit), 
   io:format("Maximum allowed processes:~p~n", [Max]), 
   
   statistics(runtime), 
   statistics(wall_clock), 
   
   L = for(1, N, fun() -> spawn(fun() -> wait() end) end), 
   {_, Time1} = statistics(runtime), 
   {_, Time2} = statistics(wall_clock), lists:foreach(fun(Pid) -> Pid ! die end, L), 
   
   U1 = Time1 * 1000 / N , 
   U2 = Time2 * 1000 / N , 
   io:format("Process spawn الوقت=~p (~p) ميكرو ثانية~n"، [U1، U2]).
   انتظار() -> 
   
   استقبال 
      موت -> لا شيء 
   fin. 
 
ل(N، N، F) -> [F()]; 
ل(I، N، F) -> [F()|ل(I+1، N، F)]. 
بداية()->
   أقصى(1000), 
   أقصى(100000).

في أي جهاز به معالج جيد، ستتمكن هاتان الوظيفتان من الحصول على الحد الأقصى. إليك مثال على مخرجات البرنامج المذكور أعلاه.

أقصى عدد للعمليات المسموح بها:262144
Process spawn الوقت=47.0 (16.0) ميكرو ثانية
أقصى عدد للعمليات المسموح بها:262144
Process spawn الوقت=12.81 (10.15) ميكرو ثانية

الاستقبال بالتأخير

في بعض الأحيان، قد تنتظر جملة الاستقبال إلى الأبد رسالة لن تأتي ابدا. قد تكون هناك العديد من الأسباب لذلك. على سبيل المثال، قد تحتوي برامجنا على أخطاء منطقية، أو قد تكون العملية التي ترسل لنا الرسالة قد انهارت قبل إرسال الرسالة.

الجملة العامة للرسائل المستقبلة المحددة بالزمن

اللغة

استقبال 
Pattern1 [when Guard1] -> 
Expressions1; 
Pattern2 [when Guard2] ->
Expressions2; 
... 
بعد الوقت -> 
Expressions 
fin

أبسط مثال هو إنشاء دالة استرخاء، كما هو موضح في البرنامج أدناه.

مثال

-مودول(helloworld). 
-تصدير([استرخاء/1, بداية/0]). 
استرخاء(T) ->
   استقبال 
   بعد T -> 
      صحيح 
   fin. 
   
بداية()->
   استرخاء(1000).

سيقوم الكود المذكور أعلاه بالاسترخاء لمدة 1000 ميليسي ثانية قبل الخروج.

الاستقبال الاختياري

كل عملية في Erlang لها صندوق بريد مرتبط بها. عند إرسال رسالة إلى هذه العملية، يتم وضع الرسالة في الصندوق البريدي. يتم فحص هذا الصندوق فقط عند تقييم جملة الاستقبال.

الجملة العامة للغة Erlang هي استقبال اختياري.

اللغة

استقبال 
Pattern1 [when Guard1] ->
Expressions1; 
Pattern2 [when Guard1] ->
Expressions1; 
... 
بعد 
الوقت ->
ExpressionTimeout 
fin

هذا هو طريقة عمل جملة الاستقبال السابقة-

  • عندما نكتب تعبير receive، سنقوم ببدء وقت التوقيت (بشرط أن يحتوي التعبير على جزء after).

  • سيتم محاولة البريد الأول في صندوق البريد، وسيتم محاولة مطابقته مع Pattern1،Pattern2 وما إلى ذلك. إذا تم التطابق بنجاح، سيتم حذف البريد من صندوق البريد وتقييم تعبير بعد النمط.

  • إذا لم يتم مطابقة أي نمط في تعبير receive مع البريد الأول في صندوق البريد، سيتم حذف البريد الأول من صندوق البريد وإدراجه في "مجموعة الحفظ". ثم سيتم محاولة البريد الثاني في صندوق البريد. استمر في هذا العمل حتى يتم العثور على رسالة مطابقة أو التحقق من جميع الرسائل في صندوق البريد.

  • إذا لم يتم مطابقة أي بريد في صندوق البريد، سيتم تعليق العملية وسيتم إعادة جدولة وقت التنفيذ عند وضع بريد جديد في صندوق البريد. يرجى ملاحظة أن الرسائل في مجموعة الحفظ لن يتم مطابقتها مرة أخرى عند استقبال رسالة جديدة؛ فقط يتم مطابقة الرسالة الجديدة.

  • بمجرد مطابقة رسالة واحدة، سيتم إعادة إدخال جميع الرسائل التي تم وضعها في مجموعة الحفظ مرة أخرى إلى صندوق البريد وفقًا لترتيب عملية الوصول. إذا تم تعيين التوقيت، يتم إزالته.

  • إذا انتهت مدة التوقيت عند انتظار الرسالة، فقيم تعبير ExpressionsTimeout وضع جميع الرسائل المحفوظة مرة أخرى في صندوق البريد وفقًا لترتيب عملية الوصول.