Dlaczego kod jądra/wątek wykonujący w kontekście przerwania nie może być uśpiony?

Czytam następujący artykuł Roberta Love

Http://www.linuxjournal.com/article/6916

To mówi

"...Omówmy fakt, że kolejki pracy działają w kontekście procesu. Jest to w przeciwieństwie do innych mechanizmów dolnej połowy, które działają w kontekście przerwań. Kod uruchamiany w kontekście przerwania nie może być uśpiony ani zablokowany, ponieważ kontekst przerwania nie ma procesu wspierającego, za pomocą którego można go przełożyć. Dlatego, ponieważ obsługa przerwań nie są związane z procesem, nie ma nic do scheduler do uśpienia i, co ważniejsze, nic do scheduler się obudzić..."

Nie rozumiem. AFAIK, scheduler w jądrze to O(1), który jest zaimplementowany poprzez bitmapę. Co powstrzymuje scehdulera przed uśpieniem kontekstu przerwania i przejęciem kolejnego procesu i przekazaniem mu kontroli?
Author: Methos, 2009-06-28

11 answers

Myślę, że to pomysł na projekt.

Jasne, można zaprojektować system, w którym można spać w przerwach, ale poza tym, aby system był trudny do zrozumienia i skomplikowany (wiele sytuacji trzeba wziąć pod uwagę), to nic nie pomaga. Tak więc z widoku projektu, declare interrupt handler as can not sleep jest bardzo jasne i łatwe do zaimplementowania.


From Robert Love (a kernel haker): http://permalink.gmane.org/gmane.linux.kernel.kernelnewbies/1791

Nie możesz spać w programie obsługi przerwań, ponieważ przerwania nie mają kontekst procesu wspierającego, a zatem nie ma co przekładać do. Innymi słowy, programy obsługi przerwań nie są powiązane z zadaniem, nie ma więc nic do "uśpienia" i (co ważniejsze) " nic do Obudź się". Muszą działać atomicznie.

To nie jest w przeciwieństwie do innych systemów operacyjnych. W większości działających systemy, przerwania nie są gwintowane. Połówki dolne często jednak są.

Powodem, dla którego obsługa błędu strony może zasnąć, jest to, że jest wywoływana tylko za pomocą kodu uruchamianego w kontekście procesu. Ponieważ jądro jest własne pamięci nie można przeglądać, tylko dostęp do pamięci w przestrzeni użytkownika może skutkować Błąd strony. Tak więc tylko kilka pewnych miejsc (np. połączenia do copy_ {to, from}_user ()) może spowodować błąd strony w jądrze. Te miejsca muszą być wykonane za pomocą kodu, który może spać (tj. proces kontekst, żadnych zamków, itd.).

 27
Author: Sam Liao,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-22 07:16:10

Więc co powstrzymuje scehdulera przed uśpieniem kontekstu przerwania i przejęciem kolejnego procesu i przekazaniem mu kontroli?

Problem polega na tym, że kontekst przerwania nie jest procesem i dlatego nie może być uśpiony.

Gdy wystąpi przerwanie, procesor zapisuje rejestry na stosie i przeskakuje do początku procedury obsługi przerwań. Oznacza to, że gdy obsługa przerwań jest uruchomiona, jest uruchomiona w kontekście proces, który był wykonywany w momencie wystąpienia przerwania. Przerwanie jest wykonywane na stosie tego procesu, a po zakończeniu obsługi przerwań proces ten wznowi wykonywanie.

Jeśli spróbujesz zasnąć lub zablokować wewnątrz programu obsługi przerwań, skończy się to nie tylko zatrzymaniem programu obsługi przerwań, ale także przerwanym procesem. Może to być niebezpieczne, ponieważ obsługa przerwań nie może wiedzieć, co robił przerwany proces, a nawet czy jest to bezpieczne proces zostanie zawieszony.

Prosty scenariusz, w którym coś mogłoby pójść nie tak, byłby impasem między obsługą przerwań a procesem, który przerywa.

  1. Process1 wchodzi w tryb jądra.
  2. Proces1 nabywa LockA .
  3. następuje przerwanie.
  4. ISR rozpoczyna wykonywanie przy użyciu stosu Process1.
  5. ISR próbuje zdobyć LockA.
  6. ISR wywołuje sen, aby czekać na LockA do uwolnienia.
W tym momencie masz impas. Process1 nie może wznowić wykonania, dopóki ISR nie zostanie wykonane z jego stosu. Ale ISR jest zablokowany czekając na Process1 aby zwolnić LockA .
 41
Author: Keith Smith,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-30 03:19:51

Ponieważ infrastruktura przełączania wątków jest w tym momencie bezużyteczna. Podczas obsługi przerwania mogą być wykonywane tylko rzeczy o wyższym priorytecie-Patrz Intel Software Developer ' s Manual on interrupt, task and processor priority. Jeśli zezwoliłbyś na uruchomienie innego wątku (co sugerujesz w swoim pytaniu, że byłoby to łatwe do zrobienia), nie byłbyś w stanie pozwolić mu na nic-jeśli spowodowałoby to błąd strony, musiałbyś użyć usług w jądrze, które są bezużyteczne podczas gdy przerywanie jest serwisowane (zobacz poniżej dlaczego).

Zazwyczaj jedynym celem procedury przerwania jest doprowadzenie urządzenia do zatrzymania przerwania i kolejkowania czegoś na niższym poziomie przerwania (w Unixie jest to zazwyczaj poziom bez przerwania, ale w Windows jest to poziom dyspozytorski, apc lub pasywny), aby wykonać ciężkie zadanie, w którym masz dostęp do większej liczby funkcji jądra/systemu operacyjnego. Zobacz - Implementowanie obsługi .

To jest właściwość działania O / S, a nie coś nieodłącznym elementem Linuksa. Procedura przerwania może zostać wykonana w dowolnym momencie, więc stan przerwania jest niespójny. Jeśli przerwałeś kod planowania wątku, jego stan jest niespójny, więc nie możesz być pewien, że możesz "spać" i przełączać wątki. Nawet jeśli chronisz kod przełączania wątku przed przerwaniem, przełączanie wątków jest bardzo wysokim poziomem funkcji O/S i jeśli chronisz wszystko, na czym polega, przerwanie staje się bardziej sugestią niż imperatywem sugerowanym przez jego nazwa.

 6
Author: Tony Lee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-26 17:12:13

Więc co powstrzymuje scehdulera przed uśpieniem kontekstu przerwania i przejęciem kolejnego procesu i przekazaniem mu kontroli?

Planowanie odbywa się po przerwaniu timera. Podstawową zasadą jest to, że tylko jedno przerwanie może być otwarte na raz, więc jeśli pójdziesz spać w przerwaniu "pobrano dane z urządzenia X", przerwanie timera nie może zostać uruchomione, aby je zaplanować.

Przerywniki zdarzają się wiele razy i nakładają się na siebie. Jeśli umieścisz przerwanie "mam dane" w uśpieniu, a następnie zdobądź więcej danych, co się stanie? Jest to na tyle mylące (i kruche), że zasada catch-all brzmi: nie spanie w przerwach. Zrobisz to źle.

 3
Author: Andres Jaan Tack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-06-27 22:52:24

Nawet gdybyś mógł uśpić ISR, nie chciałbyś tego robić. Chcesz, aby Twój ISRs był tak szybki, jak to możliwe, aby zmniejszyć ryzyko braku kolejnych przerwań.

 2
Author: Ryan Fox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-30 17:56:10

Programy obsługi przerwań wysokiego poziomu maskują operacje wszystkich przerwań o niższym priorytecie, w tym przerwań systemowego timera. W związku z tym obsługa przerwań musi unikać angażowania się w działanie, które może spowodować jego uśpienie. Jeśli funkcja obsługi śpi, system może się zawiesić, ponieważ timer jest zamaskowany i nie jest w stanie zaplanować wątku uśpienia. Czy to ma sens?

 0
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-30 17:50:36

Jeśli procedura przerwania wyższego poziomu dojdzie do punktu, w którym następna rzecz, którą musi zrobić, musi się wydarzyć po pewnym czasie, to musi umieścić żądanie w kolejce czasowej, prosząc o uruchomienie innej procedury przerwania (na niższym poziomie priorytetu) jakiś czas później.

Gdy ta procedura przerwania zostanie uruchomiona, wtedy poziom priorytetu zostanie podniesiony z powrotem do poziomu oryginalnej procedury przerwania i będzie kontynuowany. Ma to taki sam efekt jak sen.

 0
Author: John Saunders,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-07-30 17:57:59

Jądro Linuksa ma dwa sposoby przydzielania stosu przerwań. Jeden znajduje się na stosie jądra przerwanego procesu, drugi jest dedykowanym stosem przerwań na procesor. Jeśli kontekst przerwania jest zapisany na dedykowanym stosie przerwań na procesor, to rzeczywiście kontekst przerwania nie jest całkowicie powiązany z żadnym procesem. Makro" current "wytworzy nieprawidłowy wskaźnik do bieżącego uruchomionego procesu, ponieważ makro" current " z pewną architekturą jest obliczane ze wskaźnikiem stosu. Na wskaźnik stosu w kontekście przerwania może wskazywać na dedykowany stos przerwań, a nie na stos jądra jakiegoś procesu.

 0
Author: Shijun Zhou,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-03 19:25:17

Wyłączenie obsługi przerwań do zablokowania jest wyborem projektowym. Gdy niektóre dane są na urządzeniu, obsługa przerwań przechwytuje bieżący proces, przygotowuje transmisję danych i włącza przerwanie; zanim obsługa włączy bieżące przerwanie, urządzenie musi się zawiesić. Chcemy, aby nasze wejścia/wyjścia były zajęte i nasz system reagował, więc lepiej nie blokować obsługi przerwań.

Nie sądzę, aby "Stany niestabilne" były istotnym powodem. Procesy, bez względu na to, czy są w trybie użytkownika lub w trybie jądra, należy pamiętać, że mogą one zostać przerwane przez przerwania. Jeśli jakaś struktura danych w trybie jądra będzie dostępna zarówno przez obsługę przerwań, jak i bieżący proces, a stan wyścigu istnieje, to bieżący proces powinien wyłączyć lokalne przerwania, a ponadto dla architektur wieloprocesorowych, spinlocki powinny być używane podczas sekcji krytycznych.

Nie wydaje mi się również, że jeśli program obsługi przerwań został zablokowany, nie można go obudzić. Kiedy mówimy " block", zasadniczo oznacza to, że zablokowany proces czeka na jakieś zdarzenie / zasób, więc łączy się w jakąś kolejkę oczekiwania na to zdarzenie / zasób. Za każdym razem, gdy zasób jest zwolniony, proces zwalniania jest odpowiedzialny za wybudzanie procesu(ów) oczekującego (- ych).

Jednak naprawdę irytujące jest to, że zablokowany proces nie może nic zrobić w czasie blokowania; nie zrobił nic złego dla tej kary, która jest niesprawiedliwa. I nikt z pewnością nie mógł przewidzieć czasu blokowania, więc Niewinni proces musi czekać z niejasnego powodu i nieograniczonego czasu.

 0
Author: Infinite,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-01-16 23:26:31

To tylko projekt/implementacja w systemie operacyjnym Linux. Zaleta tego projektu jest prosta, ale może nie być dobra dla wymagań systemu operacyjnego w czasie rzeczywistym.

Inne systemy operacyjne mają inne projekty/implementacje.

Na przykład w Solarisie przerwania mogą mieć różne priorytety, co pozwala na to, że większość urządzeń przerwania są wywoływane w wątkach przerwań. Wątki przerwań pozwalają na uśpienie, ponieważ każdy z wątków przerwań ma osobny stos w kontekście wątku. Na konstrukcja wątków przerwań jest dobra dla wątków czasu rzeczywistego, które powinny mieć wyższe priorytety niż przerwania.

 0
Author: Oliver Yang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-31 03:47:28

Z natury rzeczy, pytanie brzmi, czy w programie obsługi przerwań można uzyskać poprawny "current" (adres do bieżącego procesu task_struktura), jeśli tak, to jest możliwe, aby zmodyfikować tam zawartość tak, aby przekształcić ją w stan "sleep", który może być z powrotem przez scheduler później, jeśli stan zostanie zmieniony. Odpowiedź może być zależna od sprzętu.

Ale w ARM jest to niemożliwe, ponieważ 'current' nie ma znaczenia dla przetwarzania w trybie przerwania. Zobacz poniższy kod:

#linux/arch/arm/include/asm/thread_info.h 
94 static inline struct thread_info *current_thread_info(void)
95 {
96  register unsigned long sp asm ("sp");
97  return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
98 }

Sp w USERZE mode i SVC mode są "takie same" ("same" tutaj nie oznacza, że są równe, zamiast tego sp trybu użytkownika wskazuje na stos przestrzeni użytkownika, podczas gdy SP r13_svc trybu svc wskazuje na stos jądra, gdzie task_struktura procesu użytkownika została zaktualizowana przy poprzednim przełączniku zadań, gdy wystąpi wywołanie systemowe, proces ponownie wchodzi w Przestrzeń jądra, gdy sp (sp_svc) nadal nie jest zmieniony, te 2 sp są ze sobą powiązane, w tym sensie są 'takie same'), więc w trybie SVC, kod jądra może poprawny "aktualny". Ale w innych trybach uprzywilejowanych, powiedzmy w trybie przerwania, sp jest 'inne', wskazuje na dedykowany adres zdefiniowany w cpu_init (). 'Current' obliczony w tym trybie będzie nieistotny dla przerwanego procesu, dostęp do niego spowoduje nieoczekiwane zachowania. Dlatego zawsze mówi się, że wywołanie systemowe może być uśpione, ale obsługa przerwań nie może, wywołanie systemowe działa w kontekście procesu, ale nie przerywa.

 0
Author: samchen2009,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-27 11:10:14