دیباگ سیستم‌های Multi Threading

Multi-Threading…

در برنامه‌های مبتنی بر RTOS، عیب‌یابی تنها به بررسی یک تابع یا متغیر محدود نمی‌شود؛ بلکه باید وضعیت Threadها، Taskها و منابع مشترک نیز تحلیل شود.

در این آموزش با روش‌های دیباگ سیستم‌های Multi-Threading در STM32 آشنا می‌شوید و یاد می‌گیرید چگونه مشکلاتی مانند Race Condition، Deadlock، Priority Inversion، Stack Overflow و خطاهای همگام‌سازی را در FreeRTOS و CMSIS-RTOS شناسایی و برطرف کنید.

همچنین استفاده از Thread Aware Debugging در STM32CubeIDE و Keil برای مشاهده وضعیت تسک‌ها، صف‌ها، Semaphoreها و Mutexها بررسی می‌شود.

فهرست صفحه

دیباگ سیستم‌های چندریسمانی (Multi-threading) چالش‌برانگیز است زیرا:

  • رفتار غیرقابل پیش‌بینی تردها.
  • تلاقی داده‌ها (Data Race).
  • بن‌بست (Deadlock) و گرسنگی (Starvation).

در این بخش، راهکارها، ابزارها و نکات مهم دیباگ این نوع سیستم‌ها را بررسی می‌کنیم.

Data Race زمانی رخ می‌دهد که دو یا چند ترد به‌طور همزمان به یک منبع مشترک (مانند متغیر) دسترسی پیدا کنند و حداقل یکی از آن‌ها نوشتن انجام دهد.

نشانه‌ها:

  • خطاهای تصادفی.
  • خروجی‌های غیرقابل پیش‌بینی.

ابزارهای کمکی:

  • Thread Sanitizer (TSan)
  • Static Analyzer

برای جلوگیری از شرایط مسابقه (Race Condition) باید از مکانیزم‌های همگام‌سازی استفاده کرد:

				
					pthread_mutex_t lock;
pthread_mutex_lock(&lock);
// critical section
pthread_mutex_unlock(&lock);

				
			

یا استفاده از Semaphore:

				
					sem_wait(&sem);
// critical section
sem_post(&sem);

				
			

مهم :

  • بخش‌های حساس (Critical Section) باید کوتاه و بهینه باشند.

Deadlock زمانی رخ می‌دهد که دو یا چند ترد منتظر هم بمانند و هیچ‌کدام نتوانند ادامه دهند.

نشانه‌ها:

  • سیستم قفل می‌کند.
  • هیچ پیشرفتی حاصل نمی‌شود.

راهکارها:

  • ترتیب مشخص قفل‌گذاری.
  • Timeout در انتظار قفل.
  • استفاده از try-lock بجای lock ساده.

ابزارهای مفید برای تشخیص بن‌بست

Helgrind (از Valgrind) :

				
					valgrind --tool=helgrind ./app

				
			

Thread Sanitizer:

				
					gcc -fsanitize=thread -g your_code.c -o your_app

				
			

این ابزارها می‌توانند قفل‌های متقابل (Circular Wait) و منابع معلق را شناسایی کنند.

برای دیباگ Multi-threading، لاگ‌گیری (Log) باید Thread-Safe باشد.

راهکارها:

استفاده از mutex در نوشتن لاگ:

				
					pthread_mutex_lock(&log_mutex);
printf("Thread %d: %s\n", id, msg);
pthread_mutex_unlock(&log_mutex);

				
			

استفاده از صف (Queue) برای مدیریت لاگ‌ها.

اگر از RTOS مثل FreeRTOS یا CMSIS-RTOS استفاده می‌کنید، Event Recorder ابزاری قدرتمند است:

  • ضبط رویدادهای تردها.
  • تحلیل زمان‌بندی و مشکلات همگام‌سازی.

مناسب برای Cortex-M و STM32.

در سیستم‌های Real-Time ممکن است تداخل اولویت (Priority Inversion) رخ دهد.

نشانه‌ها:

  • تاخیر در اجرای تردهای با اولویت بالا.

راهکار:

  • استفاده از Priority Inheritance Protocol در Mutex ها.
  • پیاده‌سازی مناسب Scheduler.

استفاده از Hook functions برای مانیتورینگ رویدادهای Thread :

مثلاً در FreeRTOS :

				
					void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
    printf("Stack overflow in task: %s\n", pcTaskName);
}
				
			

مفید برای شناسایی خطاهای ترد در زمان اجرا.

بررسی مصرف Stack هر Thread برای جلوگیری از Stack Overflow :

استفاده از uxTaskGetStackHighWaterMark در FreeRTOS :

				
					UBaseType_t uxHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
printf("Remaining stack: %u\n", uxHighWaterMark);

				
			

بهینه‌سازی مصرف حافظه و جلوگیری از کرش.

نکات کلیدی:

  • همیشه از مکانیزم همگام‌سازی ایمن استفاده کنید.
  • از ابزارهای تحلیل Thread (TSan, Helgrind) بهره ببرید.
  • لاگ‌ها را Thread-Safe بنویسید.
  • به مصرف حافظه تردها (Stack) دقت کنید.
  • Deadlock و Priority Inversion را پیشگیری و شناسایی کنید.

این راهکارها کمک می‌کنند سیستم‌های Multi-threading پایدارتر و قابل اعتمادتر طراحی کنید.

error: Content is protected !!
پیمایش به بالا