Linux: Wykorzystana całkowita zamiana = zamiana używana przez procesy +?

17

Próbuję więc zbadać, skąd bierze się zamiana w systemie o wysokim zużyciu:

# free
             total       used       free     shared    buffers     cached
Mem:        515324     508800       6524          0       4852      27576
-/+ buffers/cache:     476372      38952
Swap:       983032     503328     479704

Sumowanie wymiany użytej na proces:

# for proc in /proc/*; do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe`'"}'; done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'
0       /bin/gawk
0       /bin/sort
0       /usr/bin/readlink
28      /sbin/xxxxxxxx
52      /sbin/mingetty
52      /sbin/mingetty
52      /sbin/mingetty
52      /sbin/mingetty
56      /sbin/mingetty
56      /sbin/mingetty
60      /xxxxxxxxxxx
60      /usr/sbin/xxx
84      /usr/sbin/xxx
108     /usr/bin/xxx
168     /bin/bash
220     /sbin/init
256     /sbin/rsyslogd
352     /bin/bash
356     /bin/bash
360     /usr/sbin/sshd
496     /usr/sbin/crond
672     /usr/sbin/sshd
12972   /opt/jdk1.6.0_22/bin/java
80392   /usr/libexec/mysqld
311876  /opt/jdk1.6.0_22/bin/java
408780  Total

Co daje niższą wartość dla całkowitej wykorzystanej zamiany. Gdzie jest pozostała używana przestrzeń wymiany? Czy jest to pamięć vmalloc () w jądrze? Coś innego? Jak mogę to zidentyfikować?

Wyjście meminfo:

# cat /proc/meminfo 
MemTotal:       515324 kB
MemFree:          6696 kB
Buffers:          5084 kB
Cached:          28056 kB
SwapCached:     157512 kB
Active:         429372 kB
Inactive:        65068 kB
HighTotal:           0 kB
HighFree:            0 kB
LowTotal:       515324 kB
LowFree:          6696 kB
SwapTotal:      983032 kB
SwapFree:       478712 kB
Dirty:             100 kB
Writeback:           0 kB
AnonPages:      399456 kB
Mapped:           8792 kB
Slab:             7744 kB
PageTables:       1820 kB
NFS_Unstable:        0 kB
Bounce:              0 kB
CommitLimit:   1240692 kB
Committed_AS:  1743904 kB
VmallocTotal:   507896 kB
VmallocUsed:      3088 kB
VmallocChunk:   504288 kB
HugePages_Total:     0
HugePages_Free:      0
HugePages_Rsvd:      0
Hugepagesize:     4096 kB
ninj
źródło
Bufory i pamięć podręczna są uwzględnione i nie są powiązane z żadnym procesem.
złotowłosa
2
@goldilocks: nie, są w pamięci fizycznej. Nie sumują się.
ninj
Masz rację, myślę, że buforowanie rzeczy do wymiany byłoby bezcelowe. Myślę jednak, że rzeczy, które zostały zamienione, można tam zostawić i śledzić nawet po tym, jak proces będący własnością jest nieaktualny, o ile przestrzeń wymiany nie jest potrzebna w inny sposób; pozwala to zaoszczędzić czas później, jeśli proces ładuje tę samą stronę, a następnie ta strona musi zostać ponownie zamieniona - nadal jest w trakcie wymiany. Google „swap cache” linux-tutorial.info/modules.php?name=MContent&pageid=314 To paralela, jak wygląda rzeczywista „pamięć podręczna cache” (rzeczy zapisane w pamięci po nieistniejących procesach).
złotowłosa
... co oznacza, lol, że „buforowanie rzeczy w zamianie” nie jest tak bezcelowe, po prostu, że nie można tego osiągnąć przez zamianę pamięci podręcznej RAM.
złotowłosa
1
Czy odpowiedź nie jest taka, że ​​jądro może się zamieniać i nie jest uwzględnione w przetwarzaniu? W szczególności jądro ma obecnie całą masę procesów „przestrzeni użytkownika” ... Po prostu zgadnij.
iain

Odpowiedzi:

11

Różnica, którą obserwujesz, tak naprawdę nie wynika z tego, że przestrzeń wymiany nie jest uwzględniona. „(Usunięte)”, które jądro czasami dołącza do /proc/*/exelinków, jest generowane przez readlinki powoduje błędy analizy w skrypcie awk, a ty skutecznie nie zliczasz procesów, których pliki binarne nie są już obecne w całości.

Niektóre jądra dodają słowo „(usunięte)” do /proc/*/exedowiązań symbolicznych, gdy nie ma już oryginalnego pliku wykonywalnego procesu.

Powód, dla którego twoje polecenie pokazuje mniej niż suma, jest z tego powodu. Dane wyjściowe readlinktakich linków będą wyglądały jak „/ path / to / bin (usunięty)”, co powoduje błąd analizy, awkgdy dane wyjściowe są podstawiane z powrotem w łańcuch (nie lubi nawiasów i spacji). Na przykład zrób to:

for a in /proc/*/exe ; do readlink $a ; done | grep deleted

Zobaczysz kilka wpisów z dołączonym „(usunięty)”. Jeśli spojrzysz na użycie wymiany dla tych wpisów, ich suma byłaby zgodna z widoczną rozbieżnością, ponieważ wynikające z nich awkbłędy uniemożliwiają obliczenie ich sum i włączenie ich do ostatecznej sumy.

Jeśli uruchomisz oryginalną komendę bez przekierowywania stderr, prawdopodobnie zauważysz kilka błędów „stałej niekontrolowanej ciągu”. Błędy te wynikają z powyższego i nie powinieneś ich ignorować.

Ignorując inne potencjalne ulepszenia oryginalnego polecenia, możesz je zmodyfikować, usuwając „(usunięte)”, w ten sposób (uwaga |awk '{print $1}'dodana do readlinkwyniku):

for proc in /proc/*; \
  do cat $proc/smaps 2>/dev/null | awk '/Swap/{swap+=$2}END{print swap "\t'`readlink $proc/exe|awk '{print $1}' `'" }'; \
done | sort -n | awk '{total+=$1}/[0-9]/;END{print total "\tTotal"}'

To użycie awkdo naprawy wyniku readlinkmoże się zepsuć, jeśli nazwa zawiera spacje - możesz użyć seddowolnej metody.

Informacje o bonusie

Nawiasem mówiąc, możesz po prostu użyć smem -t. Kolumna „Zamień” pokazuje, co chcesz.

Jeśli chodzi o samodzielne obliczanie, możesz również uzyskać te informacje bardziej bezpośrednio z VmSwappola w /proc/*/status(smaps wymaga obsługi jądra i nie zawsze jest dostępny) i unikaj przekierowywania wyjścia błędu, używając odpowiedniego wzorca nazwy pliku, który pozwala uniknąć błędy na początek:

for proc in /proc/[0-9]*; do \
  awk '/VmSwap/ { print $2 "\t'`readlink $proc/exe | awk '{ print $1 }'`'" }' $proc/status; \
done | sort -n | awk '{ total += $1 ; print $0 } END { print total "\tTotal" }'

Jeśli nie potrzebujesz rzeczywistego pliku binarnego i poradzisz sobie z samą nazwą procesu, możesz uzyskać wszystko z status:

for a in /proc/*/status ; do \
  awk '/VmSwap|Name/ { printf $2 " " } END { print "" }' $a ; \
done | awk '{ total+=$2 ; print $0 } END { print "Total " total }'

I wreszcie, jeśli wystarczy mieć PID, możesz to wszystko zrobić za pomocą awk:

awk '/VmSwap/ { total += $2; print $2 "\t" FILENAME } END { print total "\tTotal" }' /proc/*/status

Uwaga:

To nie znaczy, że nie ma różnic między freei smem(ten drugi jest taki sam jak twój skrypt). Jest ich wiele (patrz na przykład https://www.google.com/search?q=smem+free , który ma więcej niż wystarczającą liczbę wyników na pierwszej stronie, aby odpowiedzieć na pytania dotyczące wykorzystania pamięci). Ale bez odpowiedniego testu nie można rozwiązać konkretnej sytuacji.

Jason C.
źródło
5

Zamiana jest również używana przez tmpfs, jeśli jądro potrzebuje więcej wolnego ram lub po prostu dlatego, że nie jest używane przez pewien czas ... więc każde użycie tmpfs może pochłonąć swap.

higuita
źródło
1
Dlaczego głosowanie negatywne? To jest absolutnie poprawne.
jlliagre