كيف أفعل ديناميكية نقل البيانات و إدارة الذاكرة عبر المواضيع في C ؟

StackOverflow https://stackoverflow.com/questions/689514

  •  22-08-2019
  •  | 
  •  

سؤال

منصة:ARM9

لغة البرمجة C

متطلبات - C عادي و لا الخارجية يبس و لا زيادة.

OS - ريكس RTOS

لدي اثنين من مؤشرات الترابط قيد التشغيل في جزءا لا يتجزأ من منصة

  1. واحد هو في سائق مستوى التعامل مع جميع الإتصالات ونقل البيانات مع الأجهزة.
  2. الموضوع الثاني يعمل التطبيق يستخدم بيانات من الأجهزة.

الفكرة هي أن فصل التطبيق الخيط من السائق الموضوع حتى نتمكن من تغيير الأجهزة التنفيذ في الأجهزة سائق الموضوع ولكن لها تأثير ضئيل على موضوع التطبيق.

التحدي هو أن البيانات الواردة من الأجهزة قد تكون ديناميكية أينحن لا نعرف مقدما مقدار الذاكرة تطبيق موضوع يجب أن جانبا عن كل طلب من الأجهزة كما يتم تحديد ذلك في وقت التشغيل.

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

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

المحلول

عدة خيارات تتبادر إلى الذهن:

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

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

حظا سعيدا!

نصائح أخرى

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

المصطلحات الخاصة بك هو مربكة و غير مشجعة.هذا هو البيرة (RT)نظام التشغيل أو لا ؟

إذا كان لديك الحقيقي OS, توجد طرق كتابة برامج تشغيل و تسليم البيانات إلى يوزرلاند.قراءة الوثائق أو استخدام أحد برامج التشغيل الموجودة كمرجع.

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

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

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

فكرتي الأولى هي استخدام مخازن دائرية.هنا بعض الأمثلة البرمجية.لا تتردد في التكيف مع هذا الخاص بك يستخدم.ربما كنت لا تريد المتغيرات العالمية.و قد لا تريد #تعرف:

#define LENGTH (1024)
#define MASK (LENGTH-1)
uint8 circularBuffer[ LENGTH ];
int circularBuffer_add = 0;
int circularBuffer_rmv = 0;

void copyIn( uint8 * circularBuffer, uint8 * inputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        circularBuffer[ circularBuffer_add ] = inputBuffer[ i ];
        circularBuffer_add = ( circularBuffer_add + 1 ) & MASK;
    } 
}

void copyOut( uint8 * circularBuffer, uint8 * outputBuffer, int n ) {
    int i;
    for( i = 0; i < n; i++ ) {
        outputBuffer[ i ] = circularBuffer[ circularBuffer_rmv ];
        circularBuffer_rmv = ( circularBuffer_rmv + 1 ) & MASK;
    } 
}

أيضا رمز أعلاه يفترض أن وحدة من البيانات هو نوع البيانات "uint8".يمكنك تغييره بحيث يستخدم بعض نوع البيانات.أو يمكنك حتى جعلها عامة واستخدام memcpy() إلى أن نسخ في circularBuffer.

الميزة الرئيسية لهذا الرمز هو كيف يتعامل مع إضافة rmv ptr.


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

فمن المهم أن التبديل مباشرة-ذاكرة الوصول لأنه رمز أعلاه يستخدم الكثير من دورات نسبة إلى DMA والذي يستخدم ما يقرب من الصفر دورات.

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