سؤال

لقد فعلت قليلا جدا من البرمجة على نظام ويندوز ولكن الآن يجب أن أكتب أول لينكس التطبيق.

أنا بحاجة إلى التحدث إلى الجهاز باستخدام UDP.يجب أن ترسل 60 الحزم الثانية مع حجم 40 بايت.إذا كنت ترسل أقل من 60 الحزم حدود 1 في الثانية ، وسوف تحدث أمور سيئة.بيانات الحزم قد يستغرق بعض الوقت إلى توليد.ولكن إذا كانت البيانات ليس على استعداد ترسل على السلك انه موافق على ارسال نفس البيانات التي تم إرسالها آخر مرة.الكمبيوتر هو سطر الأوامر فقط الإعداد فقط تشغيل هذا البرنامج.

أنا لا أعرف الكثير عن لينكس إذا كنت آمل في الحصول على فكرة عامة كيف يمكن إعداد التطبيق لتلبية هذه الاحتياجات.كنت أتمنى إجابة مثل:

جعل 2 موضوع واحد لإرسال الحزم وغيرها من الحسابات.

ولكن لست متأكدا من أن الأمر بسيط (ربما).ربما سيكون أكثر موثوقية من جعل نوعا من الشيطان أن مجرد إرسال الحزم من الذاكرة المشتركة أو ما شابه ومن ثم يكون آخر التطبيق تفعل الحسابات ؟ إذا كان بعض متعددة عملية الحل ، ما هي آلية التواصل تنصحين ؟ هل هناك طريقة أستطيع أن أعطي بلدي التطبيق أولوية أكبر من المعتاد أو شيئا من هذا القبيل ؟

PS:المزيد من الرصاص أفضل!

هل كانت مفيدة؟

المحلول

لقد قمت بنشرت هذه الإجابة لتوضيح نهج مختلف تماما مع "الواضح"، على أمل أن يكتشف شخص ما أن يكون بالضبط ما يحتاجونه. لم أكن أتوقع أن يتم اختيارها كأفضل إجابة! تعامل هذا الحل بحذر، لأن هناك مخاطر محتملة وقضايا التزامن ...

يمكنك استعمال ال setitimer () استدعاء النظام للحصول على Sigalrm (إشارة التنبيه) المرسلة إلى البرنامج الخاص بك بعد عدد محدد من MilliSeconds. إشارات أحداث غير متزامنة (مثل الرسائل قليلا) التي تقاطع البرنامج المنفذ للسماح بتشغيل معالج إشارة.

يتم تثبيت مجموعة من معالجات الإشارات الافتراضية بواسطة نظام التشغيل عند بدء تشغيل البرنامج، ولكن يمكنك تثبيت معالج إشارة مخصص باستخدام سيلى ().

لذلك كل ما تحتاجه هو موضوع واحد؛ استخدم المتغيرات العالمية بحيث يمكن لمعالج الإشارة الوصول إلى المعلومات اللازمة وإرسال حزمة جديدة أو كرر الحزمة الأخيرة حسب الاقتضاء.

إليك مثال على استحقاقك:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
int ticker = 0;

void timerTick(int dummy)
{
    printf("The value of ticker is: %d\n", ticker);
}

int main()
{
    int i;

    struct sigaction action;
    struct itimerval time;

    //Here is where we specify the SIGALRM handler
    action.sa_handler = &timerTick;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;

    //Register the handler for SIGALRM
    sigaction(SIGALRM, &action, NULL);

    time.it_interval.tv_sec = 1;       //Timing interval in seconds
    time.it_interval.tv_usec = 000000; //and microseconds
    time.it_value.tv_sec = 0;  //Initial timer value in seconds
    time.it_value.tv_usec = 1; //and microseconds

    //Set off the timer
    setitimer(ITIMER_REAL, &time, NULL);

    //Be busy
    while(1)
        for(ticker = 0; ticker < 1000; ticker++)
            for(i = 0; i < 60000000; i++)
                ;
}

نصائح أخرى

لقد قمت بمشروع مماثل: برنامج بسيط على كمبيوتر Linux مضمن، يمكن إرسال الرسائل بسرعة منتظمة.

سأذهب إلى نهج المواضيعين. أعط مؤشر الترابط إرسال أولوية أعلى قليلا، وجعلها ترسل نفس كتلة البيانات مرة أخرى إذا كانت الخيط الآخر بطيئا في حوسبة الكتل هذه.

60 حزم UDP في الثانية في الثانية مريحة للغاية على معظم الأنظمة (بما في ذلك العناصر المضمنة)، لذلك لن أقضي الكثير من العرق على تحسين مشاركة البيانات بين مؤشرات الترابط وإرسال الحزم.

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

اثنين من الخيوط كما اقترحت سوف تعمل. إذا كان لديك أنبوب () بينهما، فيمكن أن يوفر مؤشر ترابط حسابك حزم كما يتم إنشاؤه، في حين أن مؤشر ترابط Comms يستخدم تحديد () لمعرفة ما إذا كان هناك أي بيانات جديدة. إذا لم يكن الأمر كذلك، فهذا فقط يرسل آخر واحد من ذاكرة التخزين المؤقت.

قد يكون لديكم أكثر من المشكلات قليلا ...

اقتراح استخدام زوج من الأصوات تبدو وكأنه سيفعل الخدعة، طالما أن عبء أداء الحسابات ليست كبيرة جدا.

بدلا من استخدام pipe() كما اقترح من قبل Cogsy، سوف أميل إلى استخدام MUTEX لقفل جزء من الذاكرة التي تستخدمها لاحتواء إخراج مؤشر ترابط الحساب - باستخدامه كمنطقة نقل بين مؤشرات الترابط.

عندما يكون مؤشر ترابط الحساب جاهزا للإخراج إلى المخزن المؤقت، فسيحصل على MUTEX، والكتابة إلى المخزن المؤقت للنقل وإصدار Mutex.

عندما كان مؤشر ترابط الإرسال جاهزا لإرسال حزمة، فسيحاول "محاولة" لقفل Mutex. إذا كان يحصل القفل، اتخذ نسخة من المخزن المؤقت للنقل وإرسالها. إذا لم تحصل على القفل، أرسل النسخة الأخيرة.

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


تحرير: نسيت إضافة - هذه هو برنامج تعليمي جيد على pthreads على لينكس. يصف أيضا استخدام mutexes.

لم أفهم تماما مدى صعوبة هل لديك 60 حزم / مخصصات ثانية. هل انفجار 60 حزم في الثانية تملأ الشرط؟ أو هو الفاصل الزمني الثاني 1/60 2 بين كل حزمة مطلوب؟

قد يذهب هذا بعيدا عن الموضوع، ولكن هناك مشكلة مهمة أخرى هي كيفية تكوين مربع Linux. أود أن أستخدم نفسي في الوقت الحالى Linux Kernel وتعطيل جميع الخدمات غير الضرورية. من الحكمة الأخرى أن هناك مخاطرة حقيقية أن تطبيقك يفتقد حزمة في بعض الوقت، بغض النظر عن الهندسة المعمارية التي تختارها.

بأي طريقة، يجب أن تعمل اثنين من المواضيع بشكل جيد.

ستعمل مؤشرات الترابط الخاصة بك، وستحتاج إلى التأكد من قفل بنية البيانات المشتركة الخاصة بك من خلال ذلك حتى لا يرى مؤشر ترابط الإرسال في منتصف الطريق من خلال تحديث.

60 في الثانية لا يبدو صعبة للغاية.

إذا كنت تشعر بالقلق حقا من الجدولة، فقم بتعيين سياسة إرسال مؤشر ترابط إرسال رسائل الترابط لإصدار ذاكرته و MOLLALL (). بهذه الطريقة، لن يتمكن أي شيء من إيقافها عن إرسال حزمة (لا يزال بإمكانهم الخروج في وقت متأخر إذا تم إرسال أشياء أخرى على السلك في نفس الوقت)

يجب أن يكون هناك بعض التسامح من الجهاز - 60 حزمة في الثانية على ما يرام، ولكن ما هو تسامح الجهاز؟ 20 في الثانية؟ إذا فشل الجهاز إذا لم يتلق أحد، فأنا أرسلها في ثلاثة أضعاف معدل يتطلبه الأمر.

سأبقى بعيدا عن المواضيع والاستخدام العمليات و (ربما) إشارات وملفات. نظرا لأنك تقول "أشياء سيئة" قد تحدث إذا لم ترسل، فأنت بحاجة إلى تجنب قفل UPS وظروف السباق. وهذا أسهل القيام به مع عمليات منفصلة وبيانات محفوظة على الملفات.

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

على عكس النوافذ، أنت يمكن نسخ (تحرك) عبر الملف أثناء فتحه.

اتبع منذ فترة طويلة Unix أفضل الممارسات:يبقيه بسيط و وحدات فصل الإجراءات والسماح OS تفعل الكثير من العمل بالنسبة لك.

العديد من الإجابات هنا ليست على الطريق الصحيح, ولكن أعتقد أنها يمكن أن تكون حتى أكثر بساطة:

  • استخدام اثنين من عمليات منفصلة ، واحدة لإنشاء البيانات والكتابة إلى المعياري ، واحدة لقراءة البيانات من stdin وإرسالها.السماح/الإخراج الأساسي المكتبات التعامل مع دفق البيانات التخزين المؤقت بين العمليات ، والسماح نظام التشغيل التعامل مع إدارة الموضوع.

  • بناء الأساسية المرسل الأولى باستخدام جهاز توقيت حلقة العازلة من بيانات وهمية والحصول على إرسال الجهاز على التردد الصحيح.

  • جعل القادمة المرسل قراءة البيانات من stdin - يمكنك إعادة توجيه البيانات من ملف مثلا"المرسل < textdata"

  • بناء المنتجة للبيانات التالية أنابيب إنتاجها إلى المرسل مثلا"منتج | المرسل".

الآن لديك القدرة على خلق الجديد المنتجين حسب الضرورة دون العبث مع الجانب المرسل.هذا الجواب يفترض الاتصال في اتجاه واحد.

الحفاظ على الإجابة بسيطة بقدر الإمكان سوف تحصل على المزيد من النجاح ، خاصة إذا كنت لا تجيد لينكس/يونكس النظم القائمة حتى الآن.هذا هو فرصة عظيمة لتعلم نظام جديد ، ولكن لا تبالغ في القيام بذلك.فمن السهل أن تقفز إلى مجمع الإجابات عندما الأدوات المتاحة ، ولكن لماذا استخدام جرافة عندما بسيط مالج الكثير.مزامنة, الإشارات, الذاكرة المشتركة ، إلخ ، كلها مفيدة و المتاحة ، ولكن يضيف المزيد من التعقيدات التي قد لا تحتاج حقا.

وأنا أتفق مع نهج الخيطين. سيكون لدي أيضا المخازن المؤقتة الثابتة والعناية المشتركة. يجب أن يكون لخيط إرسال هذا المنطق.

loop
    wait for timer
    grab mutex
    check enum {0, 1}
    send buffer 0 or 1 based on enum
    release mutex
end loop

سيكون مؤشر الترابط الآخر هذا المنطق:

loop
    check enum
    choose buffer 1 or 0 based on enum (opposite of other thread)
    generate data
    grab mutex
    flip enum
    release mutex
end loop

بهذه الطريقة تحتوي المرسل دائما على مخزن مؤقت ساري المفعول طوال الوقت الذي يقوم بإرسال البيانات. يمكن لخيط المولد فقط تغيير مؤشر المخزن المؤقت ويمكن أن يفعل ذلك فقط إذا لم يكن الإرسال قيد التقدم. بالإضافة إلى ذلك، يجب ألا يأخذ Enum Flip الكثير من الدورات لتأخير مؤشر ترابط المرسل ذو الأولوية الأعلى لفترة طويلة جدا.

شكرا للجميع، وسوف أستخدم نصيحة الجميع. أتمنى أن أحدد المزيد من الإجابات من 1!

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top