Do komunikacji między zadaniami lub do udostępniania danych między dwoma zadaniami RTOS używamy kolejek. Ale problem z kolejkami polega na tym, że są one powolne ... Kopiują dane do bufora, następnie Mutex Handling, a następnie Transfer danych. Jest irytująco wolny, jeśli musisz przesyłać duże dane. Innym problemem jest dostęp do tej samej kolejki przez wiele zadań. Następnie obraz wygląda następująco: - Najpierw poczekaj, aby uzyskać dostęp do kolejki, następnie kolejka obsługi mutexów w kolejce, a następnie transfer danych.
Zwiększa to obciążenie systemu. Jaki może być skuteczny zamiennik kolejek?
(Myślę, że to pytanie jest niezależne od RTOS, którego używamy. Większość RTOS obsługuje kolejki tylko w ten sposób)
Odpowiedzi:
Kolejki działają w ten sposób, ponieważ jest to model transakcji bezpieczny dla wątków do komunikacji między zadaniami. Ryzykujesz uszkodzenie danych i / lub problemy z własnością w każdym mniej rygorystycznym systemie.
Czy kopiujesz dane do bufora w pamięci, a następnie przekazujesz wskaźnik z elementami kolejki, czy próbujesz przekazać wszystkie dane w samych elementach kolejki? Jeśli nie przekazujesz wskaźników, zwiększysz wydajność, robiąc to zamiast przepuszczać jeden bajt na raz przez elementy kolejki.
źródło
Jednym prostym sposobem jest umieszczenie wskaźnika w danych w kolejce i wykorzystanie danych za pomocą wskaźnika.
Pamiętaj, że w ten sposób zamieniasz bezpieczeństwo na wydajność, ponieważ musisz upewnić się, że:
Jeśli nie używasz pamięci dynamicznie alokowanej, nie musisz jej cofać przydziału, ale musisz upewnić się, że obszar pamięci nie zostanie ponownie wykorzystany przed zużyciem danych.
źródło
Kolejki bez blokady można wdrożyć w przypadku pojedynczego producenta / pojedynczego konsumenta, a często można tak zaprojektować oprogramowanie, aby zminimalizować liczbę kolejek wielu producentów lub wielu konsumentów.
Kolejkę bez blokady można tak skonstruować: Przydziel tablicę elementów, które mają być komunikowane, a także dwie liczby całkowite, nazywaj je Głową i Ogonem. Head jest indeksem w tablicy, do którego zostanie dodany następny element. Ogon jest indeksem w tablicy, w którym można usunąć następny element. Zadanie producenta odczytuje H i T, aby ustalić, czy jest miejsce na dodanie elementu; zapisuje element w indeksie H, a następnie aktualizuje H. Zadania konsumenta odczytują H i T, aby ustalić, czy są dostępne dane, odczytują dane z indeksu T, a następnie aktualizują T. Zasadniczo jest to bufor pierścieniowy, do którego dostęp mają dwa zadania, a kolejność operacji (wstaw, następnie zaktualizuj H; usuń, a następnie zaktualizuj T) zapewnia, że nie nastąpi uszkodzenie danych.
Jeśli masz sytuację z wieloma producentami i jednym konsumentem lub z jednym producentem i wieloma konsumentami, faktycznie masz pewnego rodzaju ograniczenie zasobów i nie pozostaje nic innego, jak korzystać z synchronizacji, ponieważ ograniczenie wydajności jest bardziej prawdopodobne być samotnym producentem / konsumentem niż narzut systemu operacyjnego z mechanizmem blokującym.
Ale jeśli masz wielu producentów ORAZ konsumentów, warto poświęcić czas (w przestrzeni projektowej), aby sprawdzić, czy nie możesz uzyskać bardziej skoordynowanego mechanizmu komunikacji; w takim przypadku, szeregowanie wszystkiego za pomocą pojedynczej kolejki zdecydowanie sprawia, że wydajność kolejki jest głównym wyznacznikiem wydajności.
źródło
Wydajną pracę można uzyskać w bezblokującej kolejce jednego producenta dla wielu producentów, jeśli sama kolejka zawiera elementy, które są wystarczająco małe, aby współpracować z operacją podstawową wyłączną dla magazynu ładunków, giełdą porównawczą lub podobną, i można użyć wartość zarezerwowana lub wartości zastrzeżone dla pustych miejsc w kolejce. Podczas pisania do kolejki pisarz dokonuje wymiany porównania, aby spróbować zapisać swoje dane w następnym pustym polu; jeśli to się nie powiedzie, pisarz próbuje następujące gniazdo. Chociaż kolejka utrzymuje wskaźnik do następnego pustego miejsca, wartość wskaźnika to „wskazówka”. Należy zauważyć, że jeśli system używa wymiany-porównania zamiast wyłączności ładowania magazynu, może być konieczne posiadanie „rodziny” różnych wartości „pustego gniazda”. W przeciwnym razie, jeśli między czasem program piszący znajdzie puste miejsce w kolejce i spróbuje do niego napisać, inny pisarz pisze automat, a czytelnik go czyta, pierwszy pisarz nieświadomie umieściłby swoje dane w miejscu, w którym czytelnik by ich nie widział. Ten problem nie występuje w systemach, które wykorzystują wyłącznie ładowanie do magazynu, ponieważ wyłączność do przechowywania wykryłaby, że dane zostały zapisane, mimo że zostały zapisane z powrotem do starej wartości.
źródło
Dostęp do kolejek można uzyskać bardziej efektywnie, pisząc na górze kolejki. Zwykle większość systemów RTOS obsługuje dodawanie na początku kolejki, co nie wymaga nabywania muteksu. Ale upewnij się, że używasz dodawania do przodu kolejki tak minimalnie, jak to możliwe, jeśli chcesz tylko szybciej wykonać dane. Zwykle struktury kolejek mają maksymalny limit rozmiaru, więc nie możesz umieścić wszystkich danych w kolejce, dlatego przekazanie wskaźnika jest zawsze łatwe.
Twoje zdrowie!!
źródło
Kolejki nie są z natury wolne. Ich realizacja może być.
Jeśli ślepo kopiujesz dane i używasz synchronicznej kolejki, zobaczysz spadek wydajności.
Jak wskazały inne plakaty, istnieją alternatywy bez blokady. Sprawa jednego producenta / pojedynczego konsumenta jest prosta; dla wielu producentów i konsumentów algorytm kolejki bez blokady Michaela i Scotta (są to ich nazwiska) jest standardem i jest wykorzystywany jako podstawa dla ConcurrentLinkedQueue w Javie .
W niektórych przypadkach można zoptymalizować potrzebę kolejek, ale zapewniają one gwarancje współbieżności, które zwykle zapewniają ogromne korzyści w zakresie uproszczenia systemów, umożliwiając rozdzielenie zadań.
źródło