هذا هو gensio (ينطق gen'-see-oh)، وهو إطار عمل لإعطاء رؤية متسقة لأنواع الإدخال/الإخراج المختلفة (والحزم). يمكنك إنشاء كائن جينسيو (أو جينسيو)، ويمكنك استخدام هذا الجنس دون الحاجة إلى معرفة الكثير عما يحدث بالأسفل. يمكنك تكديس جينسيو فوق آخر لإضافة وظيفة البروتوكول. على سبيل المثال، يمكنك إنشاء TCP gensio، وتكديس SSL فوق ذلك، وتكديس Telnet فوق ذلك. وهو يدعم عددًا من منافذ الإدخال/الإخراج والمنافذ التسلسلية للشبكة. كما أنه يدعم واجهات الصوت. تُسمى gensios التي يتم تكديسها على gensios الأخرى بالمرشحات.
يمكنك أن تفعل الشيء نفسه مع منافذ الاستقبال. يمكنك إعداد متقبل gensio لقبول الاتصالات في المكدس. لذا، في مثالنا السابق، يمكنك إعداد TCP للاستماع على منفذ معين وتكديس SSL وTelnet تلقائيًا في الأعلى عندما يأتي الاتصال، ولن يتم إعلامك حتى يصبح كل شيء جاهزًا.
يعمل gensio على Linux وBSD وMacOS وWindows. في نظام التشغيل Windows، يمنحك واجهة تعتمد على الأحداث قادرة على ترابط واحد (ولكن أيضًا قادرة على تعدد الخيوط) (مع توفر واجهات الحظر) لتبسيط البرمجة مع الكثير من عمليات الإدخال/الإخراج. إنه يقطع شوطًا طويلاً في جعل كتابة التعليمات البرمجية المحمولة التي تعتمد على الإدخال / الإخراج أمرًا سهلاً.
إحدى الميزات المهمة جدًا لـ gensio هي أنها تجعل إنشاء اتصالات مشفرة وموثقة أسهل بكثير من بدونها. وبعيدًا عن إدارة المفاتيح الأساسية، فهي في الواقع ليست أصعب من بروتوكول TCP أو أي شيء آخر. فهو يوفر مرونة موسعة للتحكم في عملية المصادقة إذا لزم الأمر. إنه حقًا سهل الاستخدام.
لاحظ أن صفحة دليل gensio(5) تحتوي على مزيد من التفاصيل حول أنواع gensio الفردية.
للحصول على تعليمات حول بناء هذا من المصدر، راجع قسم "البناء" في النهاية.
يتوفر عدد من الأدوات التي تستخدم gensios، كمثال ولتجربة الأشياء. هذه هي:
برنامج خفي يشبه sshd يستخدم certauth وssl وSCTP أو TCP gensios لإجراء الاتصالات. ويستخدم مصادقة PAM القياسية ويستخدم ptys. راجع gtlsshd(8) للحصول على التفاصيل.
يوجد عنصر في الأسئلة الشائعة.rst يسمى "كيفية تشغيل gtlsshd على Windows"، راجع ذلك وقسم البناء على Windows أدناه لمزيد من التفاصيل، حيث أن هناك بعض الأشياء الصعبة التي يتعين عليك التعامل معها.
الأجيال التالية متوفرة في المكتبة:
متقبل gensio الذي يأخذ سلسلة مكدس gensio كمعلمة. يتيح لك هذا استخدام gensio كمتقبل. عند بدء تشغيل conacc، فإنه يفتح gensio، وعندما يفتح gensio يُبلغ عن طفل جديد للمتقبل. عندما يغلق الطفل، فإنه يحاول فتح الطفل مرة أخرى وإجراء العملية مرة أخرى (ما لم يتم تعطيل عمليات القبول في conacc).
لماذا تريد استخدام هذا؟ لنفترض في ser2net أنك تريد توصيل منفذ تسلسلي بآخر. يمكن أن يكون لديك اتصال مثل:
connection : &con0
accepter : conacc,serialdev,/dev/ttyS1,115200
connector : serialdev,/dev/ttyS2,115200
وسوف يقوم بتوصيل /dev/ttyS1 إلى /dev/ttyS2. بدون conacc، لا يمكنك استخدام serialdev كمستقبل. سيسمح لك أيضًا باستخدام gtlsshd على منفذ تسلسلي إذا كنت تريد تسجيلات دخول مشفرة وموثقة عبر منفذ تسلسلي. إذا قمت بتشغيل gtlsshd بما يلي:
gtlsshd --notcp --nosctp --oneshot --nodaemon --other_acc
' conacc,relpkt(mode=server),msgdelim,/dev/ttyUSB1,115200n81 '
يمكنك التواصل مع:
gtlssh --transport ' relpkt,msgdelim,/dev/ttyUSB2,115200n81 ' USB2
يؤدي هذا إلى إنشاء نقل حزم موثوق به عبر منفذ تسلسلي. إن الوضع = الخادم مطلوب لتشغيل relpkt كخادم، حيث أنه سيتم تشغيله عادةً كعميل لأنه لم يتم تشغيله كقابل. يتطلب SSL gensio (الذي يعمل عبر النقل) اتصالاً موثوقًا به، لذلك لن يعمل مباشرة عبر منفذ تسلسلي.
نعم، يبدو وكأنه خليط من الحروف.
يتم استخدام عامل التصفية الموجود أعلى جينسيو الصوت ويقوم بمودم تبديل تردد الصوت، كما هو الحال في راديو الهواة AX.25.
بروتوكول راديو للهواة لحزم الراديو. لاستخدام هذا بشكل كامل، ستحتاج إلى كتابة تعليمات برمجية، لأنه يستخدم القنوات وبيانات oob لمعلومات غير مرقمة، ولكن يمكنك القيام بالأشياء الأساسية باستخدام gensiot فقط إذا كان كل ما تحتاجه هو قناة اتصال واحدة. على سبيل المثال، إذا كنت تريد الدردشة مع شخص ما عبر الراديو، وكان منفذ القبلة موجودًا على الرقم 8001 على كلا الجهازين، فيمكنك تشغيل الجهاز المستقبل:
gensiot -i ' stdio(self) ' -a
' ax25(laddr=AE5KM-1),kiss,conacc,tcp,localhost,8001 '
والتي سيتم ربطها بـ TNC وانتظار الاتصال على العنوان AE5KM-1. ثم يمكنك تشغيل:
gensiot -i ' stdio(self) '
' ax25(laddr=AE5KM-2,addr="0,AE5KM-1,AE5KM-2"),kiss,tcp,localhost,8001 '
على الجهاز الآخر. سيؤدي هذا إلى الاتصال بالجهاز الآخر عبر TNC 0 بالعنوان المحدد. بعد ذلك، سيظهر أي شيء تكتبه في أحدهما على الآخر، سطرًا تلو الآخر. اكتب "Ctrl-D" للخروج. يقوم الجزء "stdio(self)" بإيقاف تشغيل الوضع الخام، لذا فهو سطر في كل مرة وتحصل على صدى محلي. وإلا فإن كل حرف تكتبه سيرسل حزمة ولن تتمكن من رؤية ما كنت تكتبه.
للربط بنظام N5COR-11 AX.25 BBS، عليك القيام بما يلي:
gensiot -i ' xlt(nlcr),stdio(self) '
' ax25(laddr=AE5KM-2,addr="0,N5COR-11,AE5KM-2"),kiss,tcp,localhost,8001 '
تستخدم معظم أنظمة BBS CR، وليس NL، للسطر الجديد، لذلك يتم استخدام xlt gensio لترجمة هذه الأحرف الواردة.
بالطبع، نظرًا لكونك جينسيو، يمكنك وضع أي جينسيو عملي تحت ax25 الذي تريده. لذا، إذا كنت تريد اللعب أو الاختبار بدون راديو، فيمكنك إجراء ax25 عبر البث المتعدد UDP. وهنا الجانب المقبول:
gensiot -i ' stdio(self) ' -a
' ax25(laddr=AE5KM-1),conacc, '
' udp(mcast="ipv4,224.0.0.20",laddr="ipv4,1234",nocon), '
' ipv4,224.0.0.20,1234 '
وهنا جانب الموصل:
gensiot -i ' stdio(self) '
' ax25(laddr=AE5KM-2,addr="0,AE5KM-1,AE5KM-2"), '
' udp(mcast="ipv4,224.0.0.20",laddr="ipv4,1234",nocon), '
' ipv4,224.0.0.20,1234 '
القبلة غير مطلوبة لأن UDP هو بالفعل وسائط موجهة نحو الحزم. أو يمكنك استخدام برنامج greflector لإنشاء محاكاة لحالة الراديو. على الجهاز "radiopi2"، قم بتشغيل:
greflector kiss,tcp,1234
والذي سينشئ برنامجًا يعكس جميع المدخلات المستلمة لجميع الاتصالات الأخرى. ثم من جهة المقبول:
gensiot -i ' stdio(self) ' -a
' ax25(laddr=AE5KM-1),kiss,conacc,tcp,radiopi2,1234 '
والجهة المتصلة:
gensiot -i ' stdio(self) '
' ax25(laddr=AE5KM-2,addr="0,AE5KM-1,AE5KM-2"),kiss,tcp,radiopi2,1234 '
يستخدم رمز الاختبار العاكس لإجراء بعض الاختبارات، لأنه سهل الاستخدام للغاية.
وقد تم توثيق كل ذلك بالتفصيل في جينسيو(5). ما لم يُنص على خلاف ذلك، كل هذه العناصر متاحة كمستقبلين أو أعضاء متصلين.
يمكنك إنشاء أجيالك الخاصة وتسجيلها في المكتبة وتكديسها مع الأجيال الأخرى.
أسهل طريقة للقيام بذلك هي سرقة التعليمات البرمجية من جينسيو الذي يفعل ما تريد، ثم تعديله لإنشاء جينسيو الخاص بك. لسوء الحظ، لا توجد وثائق جيدة حول كيفية القيام بذلك.
يحتوي ملف التضمين include/gensio/gensio_class.h على واجهة بين مكتبة gensio الرئيسية وgensio. تأتي جميع مكالمات gensio من خلال وظيفة واحدة تحتوي على أرقام لتحديد الوظيفة المطلوبة. يجب عليك تعيين كل هذه العمليات الفعلية. وهذا أمر مؤلم إلى حد ما، ولكنه يجعل التوافق للأمام والخلف أسهل بكثير.
إن إنشاء جينسيو الخاص بك بهذه الطريقة أمر معقد إلى حد ما. يمكن أن تكون آلة الدولة لشيء كهذا معقدة بشكل مدهش. التنظيف هو الجزء الأصعب. يجب عليك التأكد من خروجك من جميع عمليات الاسترجاعات وأنه قد لا يتم استدعاء أي مؤقتات مرة أخرى في حالة السباق عند إيقاف التشغيل. فقط أبسط gensios (echo، dummy)، gensios الغريب (conadd، keepopen، stdio)، و gensios الذين لديهم قنوات (mux، ax25) ينفذون الواجهة مباشرة. كل شيء آخر يستخدم include/gensio/gensio_base.h. يوفر gensio_base آلة الحالة الأساسية لـ gensio. يحتوي على جزء مرشح (وهو اختياري) وجزء منخفض المستوى (ll)، وهو ليس كذلك.
تحتوي واجهة التصفية على بيانات يتم تشغيلها من خلالها للمعالجة. يُستخدم هذا لأشياء مثل ssl، وcertauth، وratelimit، وما إلى ذلك. وسيستخدم Filter gensios هذا. كل هذه تستخدم gensio_ll_gensio (لتكديس جينسيو فوق جينسيو آخر) لـ ll.
لكل من Gensios الطرفية LL خاص بها ولا يوجد مرشح بشكل عام. بالنسبة إلى lls المستندة إلى واصف الملف (fd)، يتم استخدام gensio_ll_fd. يوجد أيضًا ll لـ IPMI serial-over-lan (ipmisol) وللصوت. من الواضح أن معظم المحطات الطرفية (tcp، udp، sctp، المنفذ التسلسلي، pty) تستخدم fd ll.
بمجرد حصولك على جينسيو، يمكنك تجميعه كوحدة وتثبيته في $(moduleinstalldir)/<version>. بعد ذلك سوف يلتقطه الجينسيو ويستخدمه. يمكنك أيضًا ربطه بالتطبيق الخاص بك والقيام بوظيفة init من التطبيق الخاص بك.
تمت مناقشة mdns gensio بالفعل، لكن مكتبة gensio توفر واجهة mDNS سهلة الاستخدام. ملف التضمين الخاص به موجود في gensio_mdns.h، ويمكنك استخدام صفحة الدليل gensio_mdns(3) للحصول على مزيد من المعلومات عنه.
لإجراء اتصال mdns باستخدام gensiot، لنفترض أنك قمت بإعداد ser2net مع تمكين mdns مثل:
connection : &my-port
accepter : telnet(rfc2217),tcp,3001
connector : serialdev,/dev/ttyUSB1,115200N81
options :
mdns : true
ثم يمكنك الاتصال به مع gensiot:
gensiot ' mdns,my-port '
سيجد gensiot الخادم والمنفذ وما إذا كان قد تم تمكين telnet وrfc2217 وإجراء الاتصال.
بالإضافة إلى ذلك، هناك أداة gmdns تتيح لك إجراء الاستعلامات والإعلانات، ويمكن لـ gtlssh إجراء استعلامات mDNS للعثور على الخدمات. إذا كان لديك عمليات تسجيل دخول آمنة وموثقة لـ ser2net، وقمت بتمكين mdns على ser2net، مثل:
connection : &access-console
accepter : telnet(rfc2217),mux,certauth(),ssl,tcp,3001
connector : serialdev,/dev/ttyUSBaccess,115200N81
options :
mdns : true
فهو يجعل الإعداد مريحًا للغاية، حيث يمكنك فقط القيام بما يلي:
gtlssh -m access-console
هذا صحيح، يمكنك فقط استخدام اسم الاتصال مباشرة، ولا حاجة لمعرفة المضيف، سواء تم تمكين telnet أو rfc2217، أو ما هو المنفذ. لا يزال يتعين عليك إعداد المفاتيح وما إلى ذلك على خادم ser2net، بالطبع، وفقًا لهذه التعليمات.
يحتوي gensio على واجهة موجهة للكائنات تعتمد على الأحداث. تتوفر أيضًا واجهات متزامنة. أنت تتعامل مع شيئين رئيسيين في جينسيو: جينسيو ومتقبل جينسيو. يوفر gensio واجهة اتصال حيث يمكنك الاتصال وقطع الاتصال والكتابة والاستقبال وما إلى ذلك.
يتيح لك متقبل gensio استقبال الاتصالات الواردة. إذا جاء اتصال، فإنه يمنحك جينسيو.
تعتمد الواجهة على الأحداث لأنها، في معظمها، غير محظورة تمامًا. إذا قمت بفتح جينسيو، فإنك ستعطيه رد اتصال سيتم استدعاؤه عند انتهاء الاتصال، أو فشل الاتصال. الشيء نفسه بالنسبة للإغلاق. ستعيد عملية الكتابة عدد البايتات المقبولة، لكنها قد لا تأخذ كل البايتات (أو حتى أيًا من البايتات) ويجب على المتصل حساب ذلك.
تحتوي الواجهات المفتوحة والمغلقة على واجهة حظر ثانوية لتوفير الراحة. هذه تنتهي بـ _s. هذا من أجل الراحة، ولكنه ليس ضروريًا ويجب أن يكون استخدامها حذرًا لأنه لا يمكنك حقًا استخدامها من عمليات الاسترجاعات.
يتم الحديث عن عمليات الاسترجاعات والبيانات والمعلومات الواردة من gensio إلى المستخدم من خلال رد اتصال الوظيفة. اقرأ البيانات، وعندما يكون gensio جاهزًا لكتابة البيانات، يعود في رد اتصال. يتم استخدام واجهة مماثلة للاتصال من المستخدم إلى طبقة gensio، ولكنها مخفية عن المستخدم. هذا النوع من الواجهات قابل للتوسعة بسهولة، ويمكن إضافة عمليات جديدة بسهولة دون كسر الواجهات القديمة.
توفر المكتبة عدة طرق لإنشاء متقبل gensio أو gensio. الطريقة الرئيسية هي str_to_gensio() وstr_to_gensio_accepter(). توفر هذه طريقة لتحديد مجموعة من gensios أو Accepters كسلسلة وبناء. بشكل عام، يجب عليك استخدام هذه الواجهة إذا استطعت.
بشكل عام، الواجهات غير الحساسة للأداء تعتمد على السلسلة. ستشاهد ذلك في gensio_control، وفي البيانات المساعدة في واجهة القراءة والكتابة للتحكم في جوانب معينة من الكتابة.
توفر المكتبة أيضًا طرقًا لإعداد gensios الخاصة بك عن طريق إنشاء كل منها على حدة. قد يكون ذلك ضروريًا في بعض المواقف، لكنه يحد من القدرة على استخدام الميزات الجديدة لمكتبة gensio عند توسيعها.
إذا كان gensio يدعم تدفقات متعددة (مثل SCTP)، فسيتم تمرير أرقام التدفق في auxdata باستخدام "stream=n". لا يتم التحكم في التدفق بشكل فردي.
ومن ناحية أخرى، فإن القنوات عبارة عن تدفقات منفصلة للبيانات عبر نفس الاتصال. يتم تمثيل القنوات كقنوات منفصلة، ويمكن التحكم في تدفقها بشكل فردي.
هناك عدد قليل من ملفات التضمين التي قد تحتاج إلى التعامل معها عند استخدام gensios:
تم توثيق معظمها في صفحات الرجل.
لإنشاء gensios الخاصة بك، تتوفر لك ملفات التضمين التالية:
يحتوي كل ملف تضمين على الكثير من الوثائق حول الاستدعاءات والمعالجات الفردية.
يحتوي gensio على مجموعة الأخطاء الخاصة به لاستخلاصها من أخطاء نظام التشغيل (المسمى GE_xxx) وتوفير المزيد من المرونة في الإبلاغ عن الأخطاء. هذه موجودة في ملف التضمين gensio_err.h (يتم تضمينه تلقائيًا من gensio.h) ويمكن ترجمتها من أرقام إلى سلسلة ذات معنى باستخدام gensio_err_to_str(). يتم تعريف الصفر على أنه ليس خطأ.
في حالة حدوث خطأ غير معروف في نظام التشغيل، يتم إرجاع GE_OSERR والإبلاغ عن السجل من خلال واجهة سجل معالج نظام التشغيل.
أحد الأشياء المزعجة بعض الشيء بشأن gensio هو أنه يتطلب منك توفير معالج نظام التشغيل (struct gensio_os_funcs) للتعامل مع وظائف نوع نظام التشغيل مثل تخصيص الذاكرة، وكائنات المزامنة، والقدرة على التعامل مع واصفات الملفات، والمؤقتات، والوقت، وبعض الأشياء الأخرى.
توفر المكتبة العديد من معالجات نظام التشغيل. يمكنك الاتصال بـ gensio_alloc_os_funcs() لتخصيص نظام افتراضي لنظامك (POSIX أو Windows). يمكنك رؤية صفحة الرجل هذه لمزيد من التفاصيل. سيكون هذا بشكل عام هو الخيار الأفضل أداءً لنظامك.
بالنسبة لأنظمة POSIX، تتوفر معالجات نظام التشغيل لـ glib وTCL، المخصصة مع gensio_glib_funcs_alloc() وgensio_tcl_funcs_alloc(). هذه لا تعمل بشكل جيد حقًا، خاصة من وجهة نظر الأداء، وواجهات برمجة التطبيقات الخاصة بـ glib وTCL ليست مصممة بشكل جيد لما يفعله gensio. يمكن لـ TCL دعم التشغيل أحادي الخيط فقط. تحتوي عملية glib متعددة مؤشرات الترابط على مؤشر ترابط واحد فقط في كل مرة في انتظار الإدخال/الإخراج. لكنهم يعملون، ويتم إجراء الاختبارات معهم. هذه غير متوفرة على نظام التشغيل Windows بسبب سوء التجريد في اللغة العفوية وبسبب نقص الحافز على TCL.
ولكن إذا كنت تستخدم شيئًا آخر مثل X Windows، وما إلى ذلك، والذي يحتوي على حلقة أحداث خاصة به، فقد تحتاج إلى تكييف واحدة لتناسب احتياجاتك. لكن الشيء الجيد هو أنه يمكنك القيام بذلك، ودمج جينسيو مع أي شيء تقريبًا.
توجد أيضًا واجهة نادل توفر طريقة ملائمة لانتظار حدوث الأشياء أثناء تشغيل حلقة الحدث. هذه هي الطريقة التي تدخل بها بشكل عام إلى حلقة الحدث، لأنها توفر طريقة ملائمة للإشارة عند الانتهاء والحاجة إلى مغادرة الحلقة.
والتوثيق لذلك موجود في:
include/gensio/gensio_os_funcs.h
تدعم مكتبة gensio المواضيع بشكل كامل وهي آمنة تمامًا للخيوط. ومع ذلك، فهو يستخدم إشارات على نظام POSIX، وCOM على أنظمة Windows، لذلك يلزم بعض الإعداد.
يجب أن يستدعي الخيط "الرئيسي" gensio_os_proc_setup() عند بدء التشغيل ويستدعي gensio_os_proc_cleanup() عند اكتماله. يؤدي هذا إلى إعداد الإشارات ومعالجات الإشارات والتخزين المحلي على نظام التشغيل Windows وأنواع أخرى من الأشياء.
يمكنك إنشاء سلاسل رسائل جديدة من سلسلة رسائل تم إعدادها بالفعل باستخدام gensio_os_new_thread(). يمنحك هذا مؤشر ترابط نظام التشغيل الأساسي ويتم تكوينه بشكل صحيح لـ gensio.
إذا كان لديك موضوع تم إنشاؤه بوسائل أخرى تريد استخدامه في gensio، طالما أن الخيط ينشئ موضوعًا آخر ولا يقوم بأي وظائف حظر (أي نوع من الانتظار، ومعالجة الخلفية، والوظائف التي تنتهي بـ _s مثل read_s، وما إلى ذلك) ليس عليك إعدادها. بهذه الطريقة، يمكن لبعض الخيوط الخارجية كتابة البيانات، أو تنشيط سلسلة رسائل أخرى، أو القيام بأشياء من هذا القبيل.
إذا كان هناك خيط خارجي يحتاج إلى القيام بهذه الأشياء، فيجب عليه استدعاء gensio_os_thread_setup().
كما هو مذكور في قسم المواضيع، تستخدم مكتبة gensio على Unix إشارات للتنبيه بين الخيوط. لقد بحثت بجدية، ولا توجد طريقة أخرى للقيام بذلك بشكل نظيف. لكن Windows يحتوي أيضًا على بعض الأشياء التي تشبه الإشارة، وهي متوفرة أيضًا في gensio.
إذا كنت تستخدم gensio_alloc_os_funcs()، فستحصل على وظائف نظام التشغيل باستخدام الإشارة التي تم تمريرها لـ IPC. يمكنك تمرير GENSIO_OS_FUNCS_DEFAULT_THREAD_SIGNAL للإشارة إذا كنت تريد الإعداد الافتراضي، وهو SIGUSR1. سيتم حظر الإشارة التي تستخدمها والاستيلاء عليها بواسطة gensio، ولا يمكنك استخدامها.
يوفر gensio أيضًا بعض المعالجة العامة لبعض الإشارات. في نظام Unix، سيتعامل مع SIGHUP من خلال وظيفة gensio_os_proc_register_reload_handler().
في نظامي التشغيل Windows وUnix، يمكنك استخدام gensio_os_proce_register_term_handler()، الذي سيتعامل مع طلبات الإنهاء (SIGINT وSIGTERM وSIGQUIT على Unix) وgensio_os_proc_register_winsize_handler() (SIGWINCH على Unix). إن كيفية وصول هذه العناصر عبر نظام Windows أمر أكثر فوضوية بعض الشيء، ولكنها غير مرئية للمستخدم.
كافة عمليات الاسترجاعات من انتظار روتين الانتظار، وليس من معالج الإشارة. وهذا ينبغي أن يبسط حياتك كثيرا.
يمكنك الاطلاع على صفحات الرجل لمزيد من التفاصيل حول كل هذه الأمور.
لإنشاء جينسيو، الطريقة العامة للقيام بذلك هي استدعاء الدالة str_to_gensio()
بسلسلة منسقة بشكل صحيح. يتم تنسيق السلسلة على النحو التالي:
<نوع>[([<خيار>[,<خيار[...]]])][,<نوع>...][,<خيار النهاية>[,<خيار النهاية>]]
end option
مخصص للمحطات الطرفية، أو تلك الموجودة في الجزء السفلي من المكدس. على سبيل المثال، tcp,localhost,3001
سينشئ جينسيو الذي يتصل بالمنفذ 3001 على المضيف المحلي. بالنسبة للمنفذ التسلسلي، مثال على ذلك هو serialdev,/dev/ttyS0,9600N81
سيقوم بإنشاء اتصال بالمنفذ التسلسلي /dev/ttyS0.
يتيح لك ذلك تكديس طبقات جينسيو فوق طبقات جينسيو. على سبيل المثال، لوضع طبقة telnet أعلى اتصال TCP:
telnet,tcp,localhost,3001
لنفترض أنك تريد تمكين RFC2217 على اتصال telnet الخاص بك. يمكنك إضافة خيار للقيام بذلك:
telnet(rfc2217=true),tcp,localhost,3001
عند إنشاء جينسيو، يمكنك توفير رد اتصال ببيانات المستخدم. عندما تقع الأحداث على جينسيو، سيتم استدعاء رد الاتصال حتى يتمكن المستخدم من التعامل معه.
متقبل gensio يشبه gensio المتصل، ولكن مع str_to_gensio_accepter()
بدلا من ذلك. التنسيق هو نفسه. على سبيل المثال:
telnet(rfc2217=true),tcp,3001
سيتم إنشاء متقبل TCP مع وجود telnet في الأعلى. بالنسبة للمتقبلين، لا تحتاج عمومًا إلى تحديد اسم المضيف إذا كنت تريد الارتباط بجميع الواجهات الموجودة على الجهاز المحلي.
بمجرد قيامك بإنشاء جينسيو، فهو ليس مفتوحًا أو جاهزًا للعمل بعد. لاستخدامه، عليك فتحه. لفتحه قم بما يلي:
struct gensio * io ;
int rv ;
rv = str_to_gensio ( "tcp,localhost,3001" , oshnd ,
tcpcb , mydata , & io );
if ( rv ) { handle error }
rv = gensio_open ( io , tcp_open_done , mydata );
if ( rv ) { handle error }
لاحظ أنه عندما يعود gensio_open()
، فإن gensio ليس مفتوحًا. يجب عليك الانتظار حتى يتم استدعاء رد الاتصال ( tcp_open_done()
في هذه الحالة). بعد ذلك، يمكنك استخدامه.
بمجرد فتح gensio، لن تحصل على أي بيانات عليه على الفور لأن الاستلام متوقف. يجب عليك الاتصال بـ gensio_set_read_callback_enable()
لتشغيل وإيقاف ما إذا كان سيتم استدعاء رد الاتصال ( tcpcb
في هذه الحالة) عند تلقي البيانات.
عند استدعاء معالج القراءة، يتم تمرير المخزن المؤقت والطول. ولن يتعين عليك معالجة كافة البيانات إذا لم تتمكن من ذلك. يجب عليك تحديث buflen بعدد البايتات التي قمت بمعالجتها بالفعل. إذا لم تتعامل مع البيانات، فسيتم تخزين البيانات التي لم تتم معالجتها مؤقتًا في gensio لوقت لاحق. لا يعني ذلك أنه إذا لم تتعامل مع جميع البيانات، فيجب عليك إيقاف تشغيل تمكين القراءة وإلا سيتم استدعاء الحدث مرة أخرى على الفور.
إذا حدث خطأ ما في الاتصال، فسيتم استدعاء معالج القراءة مع مجموعة أخطاء. سيكون buf
و buflen
فارغين في هذه الحالة.
للكتابة، يمكنك استدعاء gensio_write()
لكتابة البيانات. يمكنك استخدام gensio_write()
في أي وقت على gensio مفتوح. قد لا يأخذ gensio_write()
كافة البيانات التي تكتبها إليه. تقوم المعلمة count
بتمرير عدد البايتات المأخوذة بالفعل في استدعاء الكتابة.
يمكنك تصميم التعليمات البرمجية الخاصة بك للاتصال gensio_set_write_callback_enable()
عندما يكون لديك بيانات لإرسالها وسيقوم gensio باستدعاء رد الاتصال الجاهز للكتابة ويمكنك الكتابة من رد الاتصال. يعد هذا أسهل بشكل عام، لكن تمكين رد الاتصال بالكتابة وتعطيله يضيف بعض الحمل.
الطريقة الأكثر فعالية هي كتابة البيانات كلما احتجت إلى ذلك وتعطيل رد الاتصال بالكتابة. إذا كانت عملية الكتابة ترجع أقل من الطلب الكامل، فإن الطرف الآخر يتم التحكم في التدفق ويجب عليك تمكين رد الاتصال بالكتابة والانتظار حتى يتم استدعاؤه قبل إرسال المزيد من البيانات.
في عمليات الاسترجاعات، يمكنك الحصول على بيانات المستخدم التي قمت بتمريرها إلى استدعاء الإنشاء باستخدام gensio_get_user_data()
.
لاحظ أنه إذا قمت بفتح جينسيو ثم أغلقته على الفور، فلا بأس بذلك، حتى لو لم يتم استدعاء رد الاتصال المفتوح. قد يتم أو لا يتم استدعاء رد الاتصال المفتوح في هذه الحالة، لذلك قد يكون من الصعب التعامل مع هذا بشكل صحيح.
يمكنك إجراء عمليات الإدخال/الإخراج المتزامنة الأساسية باستخدام gensios. يعد هذا مفيدًا في بعض المواقف التي تحتاج فيها إلى قراءة شيء ما في السطر. للقيام بذلك، اتصل:
err = gensio_set_sync ( io );
سيتوقف الجنس المعطى عن تقديم أحداث القراءة والكتابة. يتم تسليم الأحداث الأخرى. ثم يمكنك القيام بما يلي:
err = gensio_read_s ( io , & count , data , datalen , & timeout );
err = gensio_write_s ( io , & count , data , datalen , & timeout );
يتم تعيين العدد على العدد الفعلي للبايتات المقروءة/المكتوبة. قد يكون NULL إذا كنت لا تهتم (على الرغم من أن هذا ليس له معنى كبير للقراءة).
قد تكون المهلة فارغة، إذا كان الأمر كذلك فانتظر إلى الأبد. إذا قمت بتعيين مهلة، يتم تحديثها إلى مقدار الوقت المتبقي.
لاحظ أن الإشارات ستتسبب في عودتها على الفور، ولكن لم يتم الإبلاغ عن أي خطأ.
سيتم حظر عمليات القراءة حتى تأتي بعض البيانات وتعيد تلك البيانات. لا ينتظر حتى يمتلئ المخزن المؤقت. المهلة هي فترة زمنية، وسوف تنتظر القراءة هذا القدر من الوقت حتى تكتمل القراءة وتعود. المهلة ليست خطأ، سيتم فقط ضبط العدد على الصفر.
كتلة الكتابة حتى تتم كتابة المخزن المؤقت بالكامل أو تنتهي المهلة. مرة أخرى، المهلة ليست خطأ، ويتم إرجاع إجمالي البايتات المكتوبة بالفعل في العد.
بمجرد الانتهاء من إجراء عمليات الإدخال/الإخراج المتزامنة مع جينسيو، اتصل بما يلي:
err = gensio_clear_sync ( io );
وسيستمر التسليم من خلال واجهة الحدث كما كان من قبل. يجب ألا تكون في مكالمة قراءة أو كتابة متزامنة عند الاتصال بهذا، وستكون النتائج غير محددة.
لاحظ أن عمليات الإدخال/الإخراج الأخرى على أجهزة Gensios الأخرى ستظل تحدث عند انتظار الإدخال/الإخراج المتزامن
لا توجد حاليًا طريقة لانتظار العديد من الأجيال ذات الإدخال/الإخراج المتزامن. إذا كنت تفعل ذلك، فيجب عليك فقط استخدام الإدخال/الإخراج المستند إلى الحدث. إنه أكثر كفاءة، وينتهي بك الأمر إلى القيام بنفس الشيء في النهاية، على أي حال.
مثل gensio، لا يعمل متقبل gensio عند إنشائه. يجب عليك الاتصال gensio_acc_startup()
لتمكينه:
struct gensio_accepter * acc ;
int rv ;
rv = str_to_gensio_accepter ( "tcp,3001" , oshnd ,
tcpacccb , mydata , & acc );
if ( rv ) { handle error }
rv = gensio_startup ( acc );
if ( rv ) { handle error }
لاحظ أنه لا يوجد رد اتصال لاستدعاء بدء التشغيل لمعرفة متى يتم تمكينه، لأنه لا توجد حاجة حقيقية لمعرفة ذلك لأنه لا يمكنك الكتابة إليه، فهو يقوم فقط بعمليات رد الاتصال.
حتى بعد بدء تشغيل جهاز الاستقبال، فإنه لن يفعل أي شيء حتى تقوم باستدعاء gensio_acc_set_accept_callback_enable()
لتمكين رد الاتصال هذا.
عندما يتم استدعاء رد الاتصال، فإنه يمنحك جينسيو في معلمة data
المفتوحة بالفعل مع تعطيل القراءة. قد يكون للجنس المستلم من متقبل الجنس بعض القيود. على سبيل المثال، قد لا تتمكن من إغلاقه ثم إعادة فتحه.
يمكن لمتقبلي gensio إجراء عمليات قبول متزامنة باستخدام gensio_acc_set_sync()
و gensio_acc_accept_s
. راجع صفحات الرجل للحصول على التفاصيل.
يحتوي struct gensio_os_funcs
على رد اتصال مدونة فيديو للتعامل مع سجلات gensio الداخلية. يتم استدعاؤها عندما يحدث شيء مهم ولكن ليس لدى gensio طريقة للإبلاغ عن خطأ. قد يتم استدعاؤه أيضًا لتسهيل تشخيص المشكلة عند حدوث خطأ ما.
تحتوي كل من فئتي متقبل gensio و gensio على فئات فرعية للتعامل مع الإدخال / الإخراج التسلسلي وتعيين كافة المعلمات المرتبطة بالمنفذ التسلسلي.
يمكنك اكتشاف ما إذا كان gensio (أو أي من أبنائه) هو منفذ تسلسلي عن طريق استدعاء gensio_to_sergensio()
. إذا أعاد ذلك NULL، فهو ليس sergensio ولا أحد من أبنائه sergensios. إذا أعادت القيمة غير NULL، فستُرجع كائن sergensio لتستخدمه. لاحظ أن gensio الذي تم إرجاعه بواسطة sergensio_to_gensio()
سيكون هو الذي تم تمريره إلى gensio_to_sergensio()
، وليس بالضرورة gensio الذي يرتبط به sergensio مباشرة.
قد يكون sergensio عميلاً، مما يعني أنه يمكنه ضبط الإعدادات التسلسلية، أو قد يكون خادمًا، مما يعني أنه سيتلقى الإعدادات التسلسلية من الطرف الآخر من الاتصال.
معظم sergensios هي عميل فقط: serialdev (المنفذ التسلسلي العادي)، وipmisol، وstdio Accepter. حاليًا، يتمتع telnet فقط بقدرات العميل والخادم.
ملاحظة: تم إهمال واجهة python الموضحة هنا. استخدم الموجود في c++/swig/pygensio الآن.
يمكنك الوصول إلى كل واجهة gensio تقريبًا من خلال لغة python، على الرغم من أن ذلك يتم بشكل مختلف قليلاً عن واجهة C.
نظرًا لأن لغة python موجهة للكائنات بالكامل، فإن متقبلات gensios و gensio هي كائنات من الدرجة الأولى، إلى جانب gensio_os_funcs و sergensios و waiters.
إليك برنامج صغير:
import gensio
class Logger :
def gensio_log ( self , level , log ):
print ( "***%s log: %s" % ( level , log ))
class GHandler :
def __init__ ( self , o , to_write ):
self . to_write = to_write
self . waiter = gensio . waiter ( o )
self . readlen = len ( to_write )
def read_callback ( self , io , err , buf , auxdata ):
if err :
print ( "Got error: " + err )
return 0
print ( "Got data: " + buf );
self . readlen -= len ( buf )
if self . readlen == 0 :
io . read_cb_enable ( False )
self . waiter . wake ()
return len ( buf )
def write_callback ( self , io ):
print ( "Write ready!" )
if self . to_write :
written = io . write ( self . to_write , None )
if ( written >= len ( self . to_write )):
self . to_write = None
io . write_cb_enable ( False )
else :
self . to_write = self . to_write [ written :]
else :
io . write_cb_enable ( False )
def open_done ( self , io , err ):
if err :
print ( "Open error: " + err );
self . waiter . wake ()
else :
print ( "Opened!" )
io . read_cb_enable ( True )
io . write_cb_enable ( True )
def wait ( self ):
self . waiter . wait_timeout ( 1 , 2000 )
o = gensio . alloc_gensio_selector ( Logger ())
h = GHandler ( o , "This is a test" )
g = gensio . gensio ( o , "telnet,tcp,localhost,2002" , h )
g . open ( h )
h . wait ()
الواجهة عبارة عن ترجمة مباشرة إلى حد ما من واجهة C. يوجد تمثيل بايثون للواجهة في swig/python/gensiodoc.py، يمكنك رؤية ذلك للتوثيق.
تم توثيق واجهة C++ في c++/README.rst.
تعد واجهة pygensio الجديدة تطبيقًا أنظف باستخدام مديري swig بدلاً من عمليات الاسترجاعات المرمزة يدويًا في بايثون. راجع README.rst في c++/swig/pygensio. يوجد أيضًا glib وtcl OS_Funcs في الدلائل glib وtcl.
واجهة C++ الكاملة متاحة لبرامج Go من خلال مديري swig و swig. راجع c++/swig/go/README.rst للحصول على التفاصيل.
هذا هو نظام autoconf عادي، لا شيء خاص. لاحظ أنه إذا حصلت على هذا مباشرة من git، فلن يتم تضمين البنية الأساسية للبناء لديك. يوجد برنامج نصي باسم "reconf" في الدليل الرئيسي سيقوم بإنشائه لك.
إذا كنت لا تعرف شيئا عن autoconf، فإن ملف التثبيت يحتوي على بعض المعلومات، أو ابحث عنه في جوجل.
لبناء جينسيو بشكل كامل، تحتاج إلى ما يلي:
ما يلي يضبط كل شيء باستثناء openipmi على نظام التشغيل ubuntu 20.04:
- Sudo apt install gcc g++ git swig python3-dev libssl-dev pkg-config
- libavahi-client-dev avahi-daemon libtool autoconf automake جعل libsctp-dev libpam-dev libwrap0-dev libglib2.0-dev tcl-dev libasound2-dev libudev-dev
في Redhat، اختفى libwrap، لذا لن تستخدمه، ويبدو أن swig غير متاح، لذلك سيتعين عليك إنشاء ذلك بنفسك بدعم go وpython على الأقل. إليك الأمر الخاص بالأنظمة المشابهة لـ Redhat:
- Sudo yum install gcc gcc-c++ git python3-devel swig openssl-devel
- PKG-Config Avahi-Devel Libtool Autoconf Automake Make Lksctp-Tools-Devel Pam-devel
قد تضطر إلى القيام بما يلي لتمكين الوصول إلى حزم التطوير:
sudo dnf config-manager-devel-set-set
والحصول على وحدات kernel SCTP ، قد تضطر إلى القيام:
Sudo Yum تثبيت kernel-modules-extra
لاستخدام لغة GO ، يجب أن تحصل على إصدار من SWIG 4.1.0 أو أكثر. قد تضطر إلى سحب نسخة حافة النزيف من Git واستخدامها.
معالجة تكوين تثبيت Python هو جزء من الألم. بشكل افتراضي ، ستضعها برامج النصوص في أي مكان يتوقع فيه برنامج Python تثبيت برامج Python المثبتة. لا يمكن للمستخدم العادي عمومًا الوصول إلى هذا الدليل.
لتجاوز هذا ، يمكنك استخدام خيارات تكوين-مع بيثونينستول و-مع بيثونينستولليب أو يمكنك تعيين متغيرات بيئة بيثونينستولدر وبيثونينستولليبدير إلى المكان الذي تريد أن تذهب فيه المكتبات والوحدات النمطية.
لاحظ أنك قد تحتاج إلى تعيين-مع UUCP Lockp إلى Lockdir (على الأنظمة القديمة هو/var/lock ، وهو الافتراضي. عضو في مجموعات DILLOUT والقفل ليكون قادرًا على فتح الأجهزة التسلسلية و/أو الأقفال.
GO GO LANGING يتطلب تثبيت GO في المسار.
عندما واصلت إضافة Gensios إلى المكتبة ، مثل Crypto ، MDNs ، Sound ، IPMI ، SCTP ، إلخ. كان عدد التبعيات في المكتبة يخرج عن السيطرة. لماذا يجب أن تقوم بتحميل libasound ، أو libopenipmi ، إذا لم تكن بحاجة إليها؟ بالإضافة إلى ذلك ، على الرغم من أن المكتبة دعمت إضافة Gensios الخاصة بك من خلال واجهة برمجية برمجية ، إلا أنها لم يكن لديها طريقة قياسية لإضافتها للنظام حتى تتمكن من كتابة Gensio الخاصة بك والسماح للجميع على النظام باستخدامه.
تدعم مكتبة Gensio تحميل gensios ديناميكيا أو بناءها إلى المكتبة. افتراضيًا إذا قمت بإنشاء مكتبات مشتركة ، يتم تجميع جميع Gensios كوحدات للتحميل الديناميكي وتثبيته في مكان يجعله ممكنًا. إذا لم تنشئ مكتبات مشتركة ، فسيتم تضمين جميع Gensios في المكتبة. ولكن يمكنك تجاوز هذا السلوك.
لتعيين جميع gensios ليتم إنشاؤها في المكتبة ، يمكنك إضافة "-مع كل جينسيوس = نعم" على سطر الأوامر التكوين وسيقوم بإنشائها إلى المكتبة.
يمكنك أيضًا ضبطها على الجميع بواسطة إضافة "-مع كل شيء gensios = ديناميكي" ، ولكن هذا هو الافتراضي.
يمكنك أيضًا تعطيل جميع Gensios افتراضيًا من خلال تحديد "-مع كل جينسيوس = لا". ثم لن يتم بناء أي gensios افتراضيا. هذا مفيد إذا كنت تريد فقط بعض gensios ، يمكنك إيقاف كل منهم ثم تمكين ثم تلك التي تريدها.
لتعيين كيفية بناء gensios الفردية ، يمكنك القيام به "-مع-<gensio> = x" حيث X "لا (لا تبني) ، نعم (بناء في المكتبة) أو ديناميكي (محمّل ديناميكيًا قابل للتنفيذ). على سبيل المثال ، على سبيل المثال ، إذا كنت ترغب فقط في إنشاء TCP Gensio في المكتبة وجعل الراحة ديناميكية ، فيمكنك الإعداد لجميع gensios الديناميكية ثم إضافة "-مع net = yes".
يتم وضع هذه الوحدات افتراضيًا
لاحظ أن التحميل الديناميكي متاح دائمًا ، حتى لو كنت تبني في جميع Gensios في المكتبة. لذلك لا يزال بإمكانك إضافة Gensios الخاص بك عن طريق إضافة ثم إلى الدليل المناسب.
سيتم تحميل gensios أولاً من متغير البيئة ld_library_path ، ثم من gensio_library_path ، ثم من الموقع الافتراضي.
MacOS ، كونه نوعًا من * nix ، يبني بشكل نظيف مع homebrew (https://brew.sh). يجب عليك ، بالطبع ، تثبيت جميع المكتبات التي تحتاجها. معظم كل شيء يعمل ، مع الاستثناءات التالية:
* CM108GPIO * SCTP * قفل UUCP
يتم استخدام رمز DNSSD المدمج في MDNs ، لذلك لا يلزم Avahi.
قفل قطيع أعمال المنافذ التسلسلية ، لذا فإن قفل UUCP غير مطلوب حقًا.
يجب أن يعمل OpenIpmi ، لكنه غير متوفر في Homebrew ، لذا سيتعين عليك بناءها بنفسك.
تثبيت البرنامج الضروري:
- PKG تثبيت GCC Portaudio Autoconf Automake libtool mdnsresponder swig
- اذهب بيثون 3 gmake
يجب عليك استخدام Gmake لتجميعه ، لسبب ما ، لا يقبل Make On BSD المتغير "C ++" في قائمة المتطلبات. ما يلي لا يعمل ولا يتم تجميعه:
* SCTP * ipmisol * CM108GPIO
أضف ما يلي إلى /etc/rc.conf:
mdnsd_enable = نعم
وإعادة التشغيل أو بدء الخدمة.
فشل pty gensio في اختبار oomtest (oomtest 14) ، ويبدو أن هناك شيء ما مع bsd ptys. أرى حرف 07 يتم إدخاله في دفق البيانات في الحالات. لم أقضي الكثير من الوقت في ذلك ، ولكن بما أن هذا يتم اختباره بشدة على Linux و MacOS ، فلا أعتقد أن المشكلة في رمز Gensio.
يمكن بناء مكتبة Gensio تحت Windows باستخدام MingW64. الأشياء التالية لا تعمل:
* SCTP * بام * libwrap * ipmisol
لا تحتاج أيضًا إلى تثبيت ALSA ، فهو يستخدم واجهة صوت Windows للصوت.
يستخدم CM108GPIO واجهات Windows الأصلية ، لذلك لا يلزم UDEV.
يتم استخدام واجهات MDNS المدمجة في Windows ، لذلك لا تحتاج إلى Avahi أو DNSSD. ستحتاج إلى تثبيت مكتبة PCRE إذا كنت تريد تعبيرات منتظمة فيه.
تحتاج إلى الحصول على msys2 من https://msys2.org. ثم قم بتثبيت Autoconf و Automake و Libtool و Git و Make و Swig كأدوات مضيفة:
Pacman -S Autoconf Automake Libtool Git Make Swig
يجب عليك تثبيت إصدار MingW-W64-X86_64-xxx لجميع المكتبات أو إصدار MingW-W64-I686-XXX لجميع المكتبات. 32 بت لم يتم اختبارها جيدًا:
Pacman -S Mingw-W64-X86_64-GCC mingw-w64-x86_64-python3 Mingw-W64-X86_64-PCRE Mingw-W64-X86_64-Openssl
لـ Mingw64 ، أو لـ UCRT64:
PACMAN -S Mingw-W64-UCRT-X86_64-GCC mingw-w64-ucrt-x86_64-python3 mingw-w64-ucrt-x86_64-pcre Mingw-W64-UCRT-X86_64-OPENSSL
لـ GO ، قم بالتثبيت من https://go.dev وتسجيل الخروج وتسجيل الدخول مرة أخرى. يجب أن يكون في المسار ، ولكن إذا لم يكن كذلك ، فستحتاج إلى إضافته إلى المسار. لم أحصل على العمل على Mingw32 ، لكنني لم أحاول نسخة 32 بت من Go.
بالنسبة لـ GTLSSHD ، -لا يوجد معنى على Windows. بدلاً من ذلك ، فإن sysconf dir نسبة إلى تصحيح القابل للتنفيذ ، في ../etc/gtlssh. لذلك إذا كان GTLSSHD في:
C:/ملفات البرنامج/Gensio/Bin/GTLSSHD
سيكون Sysconfdir:
C:/ملفات البرنامج/gensio/etc/gtlssh
للتثبيت القياسي ، يمكنك تشغيل:
../configure -sbindir =/gensio/bin -libexecdir =/gensio/bin -mandir =/gensio/man-includedir =/gensio/include ---with-pythoninstall =/gensio/python3-prefix =/gensio
وعندما تقوم بتشغيل "اجعل تثبيت DestDir = ..." وتعيين Destdir على المكان الذي تريد أن يذهب إليه ، مثل "C:/Program Files". ثم يمكنك إضافة ذلك إلى المسار باستخدام لوحة التحكم. لاستخدام GTLSSHD ، يمكنك إنشاء دليل ETC/GTLSSHD في دليل Gensio. يجب عليك تعيين الأذونات على هذا الدليل حتى يتم الوصول إلى النظام والمسؤولين فقط ، مثل:
PS C: Program Files (x86) gensio etc> icacls gtlssh GTLSSH NT Authority System: (OI) (CI) (F) بنيت المسؤولون: (OI) (CI) (F)
وإلا سيفشل GTLSSHD مع خطأ في الأذونات على المفتاح. يمكنك تعيين هذه الإذن على ملف .key بدلاً من الدليل ، ولكن سيتعين عليك تعيينه مرة أخرى في كل مرة تقوم فيها بإنشاء مفتاح جديد.
لاستخدام برنامج التحويل البرمجي INNO ، قم "اجعل تثبيت DestDir = $ home/install" ثم قم بتشغيل Inno على gensio.iss. سيقوم بإنشاء مثبت قابل للتنفيذ لتثبيت Gensio.
ثم تحتاج إلى إزالة ملفات .la من دليل التثبيت ، لأنها تربط بين الارتباط بأشياء أخرى:
RM $ home/install/gensio/lib/*. la
هناك عدد من الاختبارات لـ Gensios. يتم تشغيلها جميعًا على Linux إذا كان لديك وحدة Kernel Serialsim. إلى جانب المنفذ التسلسلي ، فإنها تعمل على منصات أخرى حيث يتم دعم Gensios على هذا المنصة.
تتطلب اختبارات المنفذ التسلسلي وحدة kernel serialsim وواجهة بيثون. هذه في https://github.com/cminyard/serialsim وتسمح للاختبارات باستخدام منفذ تسلسلي محاكي لقراءة خط التحكم في المودم ، وأخطاء الحقن ، إلخ.
يمكنك الحصول على بدون SerialSim إذا كان لديك ثلاثة أجهزة تسلسلية: أحدهم مدمن مخدرات في وضع الصدى (RX و TX مرتبطان معًا) واثنين من الجهاز التسلسلي مدمن مخدرات معًا ، هل يذهب I/O على جهاز واحد إلى/يأتي من الآخر. هذا يجب أن يعمل على منصات غير لينكس. ثم اضبط متغيرات البيئة التالية:
export GENSIO_TEST_PIPE_DEVS= " /dev/ttyxxx:/dev/ttywww "
export GENSIO_TEST_ECHO_DEV= " /dev/ttyzzz "
لن يكون قادرًا على اختبار مودم أو RS485.
كما أنها تتطلب برنامج IPMI_SIM من مكتبة OpenIPMI على https://github.com/cminyard/openipmi لتشغيل اختبارات IPMISol.
لتشغيل الاختبارات ، تحتاج إلى تمكين بعض التصحيح الداخلي للحصول على التأثير الكامل. تريد عمومًا تشغيل شيء مثل:
./configure --enable-internal-trace CFLAGS= ' -g -Wall '
يمكنك تشغيل -o3 في cflags ، أيضًا ، إذا أردت ، ولكنه يجعل تصحيح الأخطاء أكثر صعوبة.
هناك نوعان أساسيان من الاختبارات. اختبارات Python هي اختبارات وظيفية تختبر كل من واجهة Python ومكتبة Gensio. حاليا هم على ما يرام ، ولكن هناك متسع كبير للتحسين. إذا كنت ترغب في المساعدة ، يمكنك كتابة الاختبارات.
اعتاد اختبار Oomtest أن يكون مختبرًا خارج الذاكرة ، ولكنه تحول إلى شيء أكثر شمولاً. يولد برنامج Gensiot مع متغيرات بيئة محددة لتسبب فشله في بعض النقاط ، وللقيام بتسرب الذاكرة وفحوصات الذاكرة الأخرى. يكتب بيانات إلى gensiot من خلال stdin الخاص بها ويتلقى بيانات عن stdout. بعض الاختبارات (مثل serialdev) تستخدم صدى. تقوم الاختبارات الأخرى بإجراء اتصال منفصل عبر الشبكة وتدفق البيانات على حد سواء إلى stdin وتعود فوق الاتصال المنفصل ، ويتدفق إلى الاتصال المنفصل ويعود عبر stdout. oomtest متعدد الخيوط ويمكن التحكم في عدد المواضيع. وجدت Oomtest الكثير من الأخطاء. يحتوي على الكثير من المقابض ، ولكن عليك أن تنظر إلى الكود المصدري للخيارات. يجب توثيقه ، إذا كان شخص ما يرغب في التطوع ...
لإعداد fuzzing ، قم بتثبيت AFL ، ثم قم بتكوين ما يلي:
mkdir Zfuzz ; cd Zfuzz
../configure --enable-internal-trace=yes --disable-shared --with-go=no
CC=afl-gcc CXX=afl-g++
أو استخدم Clang ، إذا كان ذلك متاحًا:
../configure --enable-internal-trace=yes --disable-shared --with-go=no
CC=afl-clang-fast CXX=afl-clang-fast++ LIBS= ' -lstdc++ '
لست متأكدًا من السبب في أن الشيء LIBS ضروري أعلاه ، لكن اضطررت إلى إضافته للحصول عليه للتجميع.
ثم بناء. ثم "اختبارات القرص المضغوط" وتشغيلها "اجعل test_fuzz_xxx" حيث XXX هي واحدة من: certauth ، mux ، ssl ، telnet ، أو relpkt. ربما ستحتاج إلى ضبط بعض الأشياء ، سوف تخبرك AFL. لاحظ أنه سيتم تشغيله إلى الأبد ، ستحتاج إلى ^C عند الانتهاء.
يحتوي Makefile في الاختبارات/makefile.am على تعليمات حول كيفية التعامل مع الفشل في إعادة إنتاج تصحيح الأخطاء.
من السهل جدًا تشغيل تغطية التعليمات البرمجية على المكتبة. تحتاج أولاً إلى تكوين الكود لتمكين التغطية:
mkdir Ocov ; cd Ocov
../configure --enable-internal-trace=yes
CC= ' gcc -fprofile-arcs -ftest-coverage '
CXX= ' g++ -fprofile-arcs -ftest-coverage '
ترجمة وتشغيل "اجعل الشيك".
لإنشاء التقرير ، قم بتشغيل:
gcovr -f ' .*/.libs/.* ' -e ' .*python.* '
هذا سوف يولد ملخص. إذا كنت ترغب في رؤية تغطية الخطوط الفردية في ملف ، فيمكنك القيام بذلك:
cd lib
gcov -o .libs/ * .o
يمكنك النظر في ملفات .gcov الفردية التي تم إنشاؤها للحصول على معلومات حول ما يتم تغطيته. انظر مستندات GCOV للحصول على التفاصيل.
في وقت كتابة هذا التقرير ، كنت أحصل على تغطية رمز بنسبة 74 ٪ ، لذلك هذا جيد جدًا. سأعمل على تحسين ذلك ، في الغالب من خلال اختبار وظيفي محسّن.
يتم استخدام Ser2Net لاختبار بعض الأشياء ، وخاصة تكوين المنفذ التسلسلي (TermiOS و RFC2217). يمكنك إنشاء Ser2Net مقابل إصدار GCOV من مكتبة Gensio وتشغيل "Make Check" في Ser2Net للحصول على تغطية على تلك الأجزاء. مع ذلك ، أرى حوالي 76 ٪ تغطية ، لذلك لا يضيف الكثير إلى المجموع.
سيكون من الجيد أن تكون قادرًا على الجمع بين هذا مع الضباب ، لكنني لست متأكدًا من كيفية القيام بذلك. AFL هل هو شيء خاص بتغطية الكود. يبدو أن هناك حزمة AFL-COV التي دمجت بطريقة أو بأخرى GCOV ، لكنني لم أبحث عنها.