🌱 RTOS 07. Giao tiếp giữa các task bằng cơ chế hàng đợi - Queue
Như mình giới thiệu ở những bài trước, chúng ta đã có những hiểu biết nhất định về RTOS. Vậy thực chất các task là các chương trình nhỏ độc lập với nhau, và chạy tuần tự theo việc lập lịch - Scheduling. Vậy, các task này muốn giao tiếp với nhau, chúng cần có những cơ chế giao tiếp khác nhau.
Các nội dung chính
👉 Dùng biến toàn cục - Global Variable?
Thường thì chúng ta sẽ nghĩ đến việc giao tiếp giữa chương trình main với chương trình con phục vụ ngắt trong chương trình thông thường, chúng ta có thể dùng biến toàn cục - Global Variable.
OK, trong chương trình thông thường thì khá đơn giản rồi, nhưng với RTOS, khi có rất nhiều task muốn truyền dữ liệu cho nhau, thì việc dùng Global Variable sẽ dẫn đến 2 trường hợp:
- Task A và Task B giao tiếp với nhau bằng global_var1. Task B và Task C giao tiếp với nhau bằng global_var2. Task C giao tiếp với Task A bằng global_var3.... Nếu có rất nhiều task, thì chúng ta sẽ phải khai báo rất nhiều biến global (Ở đây 3 Task đã phải sử dụng 3 biến global).
⇨ Hậu quả là khá tốn bộ nhớ nếu có nhiều Task 😪😪😪 - Vậy nếu các Task này dùng chung 1 biến global thì sao? Với ví dụ trên nếu Task A đang muốn truyền một giá trị là 5 sang Task B bằng biến Global X. Thì Task B chưa kịp nhận được thì Task C chen ngang và cướp mất biến này, thay đổi nó X = 4, sau đó Task B nhận được giá trị X = 4.
⇨ Hậu quả là việc sai lệch dữ liệu 😪😪😪
Nhìn chúng chúng ta có thể kết luận là Global Variable có quá nhiều vấn đề ở đây, vì vậy người ta mới sử dụng Queue để truyền nhận dữ liệu giữa các Task.
👉 Queue - Hàng đợi
Queue mà chúng ta thường biết đến là cấu trúc dữ liệu Queue - Hàng đợi. Trong các hệ điều hành thời gian thực (RTOS), queue là một công cụ quan trọng được sử dụng để giao tiếp và chia sẻ dữ liệu giữa các task hoặc giữa một task và ISR (Interrupt Service Routine). Queue đảm bảo rằng dữ liệu được truyền an toàn và có trình tự ngay cả khi các task hoặc ISR chạy không đồng bộ.
Queue trong RTOS cũng hoạt động theo cơ chế FIFO - First In First Out, tức là dữ liệu nào đi vào queue trước sẽ được sử dụng trước, giống như "văn hóa xếp hàng" của con người.
Trên đây là hoạt động cơ bản của Queue. Queue trong RTOS được xây dựng trên hardware, về cơ bản giống như một mảng các ô nhớ, độ dài của Queue do người dùng quy định.
Cơ chế hoạt động:
- Khi một Task muốn truyền dữ liệu sang Task khác, nó sẽ đặt dữ liệu này vào Queue, cùng với đó là ID của Task mà nó muốn truyền tới.
- Hãy tưởng tượng Queue giống như một "bưu điện" đơn giản, khi nhiều người cùng chuyển thư (dữ liệu) cho người khác, thì chúng ta cần có địa chỉ người nhận (ID của task nhận). Và bưu điện này sẽ khá công bằng, khi mà thư nào đến trước thì sẽ được gửi đi trước.
Ưu điểm:
- Tốn khá ít bộ nhớ (Nếu như người dùng ước lượng được độ dài tối đa của Queue).
- Việc truyền nhận sẽ rất ít bị mất hay sai lệch dữ liệu.
👉 Hai loại Queue sử dụng trong RTOS
Về cơ bản thì RTOS sử dụng 2 loại Queue đó là Message Queue và Mail Queue. Sự khác nhau đặc trưng nhất giữa hai Queue này là Message Queue thì "Xếp 1 hàng" còn Mail Queue thì "Xếp nhiều hàng".
Cụ thể, Messege Queue sẽ sử dụng Queue theo kiểu Serial, dữ liệu được sắp xếp theo mảng một chiều. Trong khi Mail Queue sẽ sử dụng Queue theo kiểu Block, mảng đa chiều.
Cụ thể 2 hình bên dưới sẽ nói rõ hoạt động của 2 kiểu Queue này (Tham khảo arm.vn)