2013-06-07 15 views
13

W procesorze wieloprocesorowym każdy rdzeń może mieć własne zmienne. Sądzę, że są to różne zmienne w różnych adresach, chociaż są w tym samym procesie i mają tę samą nazwę.W jaki sposób implementowane są wskaźniki percpu w jądrze systemu Linux?

Ale zastanawiam się, w jaki sposób jądro to wdraża? Czy rozładowuje pamięć, aby zdeponować wszystkie wskaźniki perkpu, i za każdym razem, gdy przekierowuje wskaźnik do pewnego adresu z przesunięciem lub czymś?

Odpowiedz

20

Normalne zmienne globalne nie są na procesor. Zmienne automatyczne są na stosie, a różne procesory używają innego stosu, więc naturalnie otrzymują oddzielne zmienne.

Przypuszczam, że odnosisz się do infrastruktury zmiennych na procesor Linuxa.
Większość magii jest tutaj (asm-generic/percpu.h):

extern unsigned long __per_cpu_offset[NR_CPUS]; 

#define per_cpu_offset(x) (__per_cpu_offset[x]) 

/* Separate out the type, so (int[3], foo) works. */ 
#define DEFINE_PER_CPU(type, name) \ 
    __attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name 

/* var is in discarded region: offset to particular copy we want */ 
#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) 
#define __get_cpu_var(var) per_cpu(var, smp_processor_id()) 

Makro RELOC_HIDE(ptr, offset) prostu przesuwa ptr przez daną przesunięcie w bajtach (niezależnie od rodzaju wskaźnika).

Co robi?

  1. Definiując DEFINE_PER_CPU(int, x) oznacza liczbę całkowitą __per_cpu_x tworzony jest w specjalnej sekcji .data.percpu.
  2. Po załadowaniu jądra ta sekcja jest ładowana wiele razy - raz na procesor (ta część magii nie znajduje się w powyższym kodzie).
  3. Tablica __per_cpu_offset jest wypełniona odległościami między kopiami. Zakładając użycie 1000 bajtów danych na procesor, __per_cpu_offset[n] będzie zawierać 1000*n.
  4. Symbol per_cpu__x zostanie przeniesiony, podczas ładowania, do CPU 0's per_cpu__x.
  5. __get_cpu_var(x), po uruchomieniu na procesorze 3, przetłumaczy się na *RELOC_HIDE(&per_cpu__x, __per_cpu_offset[3]). Zaczyna się to od CPU 0: x, dodaje przesunięcie pomiędzy danymi procesora 0 i CPU 3, a ostatecznie usuwa wynikowy wskaźnik.
+0

Dziękuję za Twój ansser, ale wciąż mam pytania, nowe do smp, więc bez obrazy dla twojego pomysłu. Po pierwsze, pomyślałem, że ten sam proces powinien mieć ten sam stos, tutaj jest definicja wątku w POSIX "... a zmienne automatyczne, są dostępne dla wszystkich wątków w tym samym procesie.". Zmienna automatyczna jest współdzielona przez wątki. Różne procesory mogą mieć inny rejestr segmentu stosu, ale zawartość powinna być taka sama. Po drugie, czy możemy powiedzieć, że możemy uzyskać dostęp do innej zmiennej procesora, jeśli chcemy, po prostu wycofać offset uzyskany przez percpu? – dspjm

+0

Gdy dwa wątki wywołują funkcję 'foo', która ma automatyczną zmienną' x', istnieją dwa stosy i dwa wystąpienia 'x'. Każdy ma inny adres, a oba wątki mogą uzyskać dostęp do obu, jeśli mają adres. W przypadku zmiennych per-cpu Linuksa 'per_cpu (var, cpu)' umożliwia dostęp do zmiennych cpu. – ugoren

+0

W jaki sposób sekcja .data.percpu określa, czy zmienna percpu jest zadeklarowana na stosie lub sterty? – user31986

Powiązane problemy