Wie lade ich alle laufenden Anwendungen aus dem Auslagerungsspeicher in den Arbeitsspeicher zurück?

20

Wenn auf meinem Desktop nicht mehr genügend Arbeitsspeicher zur Verfügung steht und häufig Daten ausgetauscht werden, kann ich die Anwendung freigeben oder beenden, wodurch mein Arbeitsspeicher verschwendet wird. Aber nachdem alle meine Desktops / Anwendungen ausgetauscht wurden und schrecklich langsam sind, kennen Sie eine Möglichkeit, meine Desktops / Anwendungen "auszutauschen" (aus dem Auslagerungsspeicher in den Arbeitsspeicher zu laden)?

profy
quelle
Anstatt das gesamte System mit swapon/ auszutauschen swapoff(wie es die derzeit akzeptierte Antwort nahelegt), möchten Sie möglicherweise Ihren Display Manager und alle untergeordneten Elemente enttauschen, indem Sie deren Prozessspeicher entleeren (wodurch das Enttauschen erzwungen wird). Siehe auch „So erzwingen Sie das Einlagern eines ausgelagerten zsh-Prozesses?“ Beim Stapelüberlauf.
Zrajm

Antworten:

16

Wenn Sie wirklich wieder genügend RAM zur Verfügung haben, können Sie diese Sequenz (als root) verwenden:

$ swapoff -a
$ swapon -a

(um das explizite Einlagern all Ihrer Anwendungen zu erzwingen)

(unter der Annahme, dass Sie Linux verwenden)

maxschlepzig
quelle
Auch wenn Sie kein IIRC verwenden, werden so viele Daten wie möglich verschoben. Während es Cache & Co beschädigen kann. es ist manchmal nützlich.
Maciej Piechotka
18

Das folgende schnelle Python-Skript speichert den Speicher eines Prozesses in stdout. Dies hat den Nebeneffekt, dass ausgelagerte Seiten oder zugeordnete Dateien geladen werden. Nennen Sie es als cat_proc_mem 123 456 789wo die Argumente Prozess-IDs sind.

Dieses Skript ist völlig Linux-spezifisch. Es ist möglicherweise anpassbar an andere Systeme mit einer ähnlichen /procStruktur (Solaris?), Aber vergessen Sie nicht, es unter z. B. * BSD auszuführen. Selbst unter Linux müssen Sie möglicherweise die Definition c_pid_tund die Werte von PTRACE_ATTACHund ändern PTRACE_DETACH. Dies ist ein Proof-of-Principle-Skript, das nicht als Beispiel für eine gute Programmierpraxis gedacht ist. Benutzung auf eigene Gefahr.

Linux stellt den Speicher eines Prozesses zur Verfügung als /proc/$pid/mem. Nur bestimmte Adressbereiche sind lesbar. Diese Bereiche können durch Lesen der Speicherzuordnungsinformationen aus der Textdatei ermittelt werden /proc/$pid/maps. Die Pseudodatei /proc/$pid/memkann nicht von allen Prozessen gelesen werden, die die Berechtigung zum Lesen haben: Der Reader-Prozess muss aufgerufen haben ptrace(PTRACE_ATTACH, $pid).

#!/usr/bin/env python
import ctypes, re, sys

## Partial interface to ptrace(2), only for PTRACE_ATTACH and PTRACE_DETACH.
c_ptrace = ctypes.CDLL("libc.so.6").ptrace
c_pid_t = ctypes.c_int32 # This assumes pid_t is int32_t
c_ptrace.argtypes = [ctypes.c_int, c_pid_t, ctypes.c_void_p, ctypes.c_void_p]
def ptrace(attach, pid):
    op = ctypes.c_int(16 if attach else 17) #PTRACE_ATTACH or PTRACE_DETACH
    c_pid = c_pid_t(pid)
    null = ctypes.c_void_p()
    err = c_ptrace(op, c_pid, null, null)
    if err != 0: raise SysError, 'ptrace', err

## Parse a line in /proc/$pid/maps. Return the boundaries of the chunk
## the read permission character.
def maps_line_range(line):
    m = re.match(r'([0-9A-Fa-f]+)-([0-9A-Fa-f]+) ([-r])', line)
    return [int(m.group(1), 16), int(m.group(2), 16), m.group(3)]

## Dump the readable chunks of memory mapped by a process
def cat_proc_mem(pid):
    ## Apparently we need to ptrace(PTRACE_ATTACH, $pid) to read /proc/$pid/mem
    ptrace(True, int(pid))
    ## Read the memory maps to see what address ranges are readable
    maps_file = open("/proc/" + pid + "/maps", 'r')
    ranges = map(maps_line_range, maps_file.readlines())
    maps_file.close()
    ## Read the readable mapped ranges
    mem_file = open("/proc/" + pid + "/mem", 'r', 0)
    for r in ranges:
        if r[2] == 'r':
            mem_file.seek(r[0])
            chunk = mem_file.read(r[1] - r[0])
            print chunk,
    mem_file.close()
    ## Cleanup
    ptrace(False, int(pid))

if __name__ == "__main__":
    for pid in sys.argv[1:]:
        cat_proc_mem(pid)

Siehe auch weitere Informationen über/proc/$pid/mem .

unswap () {
  cat_proc_mem "$@" >/dev/null
}
Gilles 'SO - hör auf böse zu sein'
quelle
2
Dies ist eines der coolsten Dinge, die ich je beim Stapelaustausch gesehen habe. Ein dickes Lob für das Posten! Es gibt so viele gute Nuggets, die man daraus ziehen kann.
Dan
Leider konnte ich dieses Skript nicht zum Laufen bringen. Mit Python 2 wird der Fehler angezeigt, dass der Wert r [0] zu groß ist. Auf Python 3 (nach der Behebung einiger kleinerer Probleme) erhalte ich OSError: [Errno 5] Eingabe- / Ausgabefehler bei chunk = mem_file.read (r [1] - r [0]) und das Programm, mit dem ich es ausgeführt habe, hängt in beiden Fällen Fälle.
barteks2x
@ Barteks2x Es tut mir leid, ich habe momentan nicht die Zeit, dieses Skript fehlersicher zu machen. Zumindest auf Computern, auf denen es nicht zu viele Sicherheitsbeschränkungen gibt, funktioniert dies. Das Programm wird angehalten, während es verfolgt wird. Senden Sie ein SIGCONT ( kill -CONT 1234wobei 1234 die PID ist), um es fortzusetzen .
Gilles 'SO- hör auf böse zu sein'
@ Barteks2x: Ich habe einige Fehlerprüfung hinzugefügt hier . Dadurch funktioniert das Skript auch auf IOErrors aus / dev / dri / card0 und OverflowErrors aus [vsyscall]. (Es wird auch der Problembereich ausgedruckt).
Hackerb9
6

Der Vollständigkeit halber kann GDB das Prozessabbild sichern. Ich habe nicht überprüft, ob es das Auslagern aufhebt, aber es muss --- es gibt keine andere Möglichkeit, den gesamten Prozessspeicher auszulesen:
gdb -p $mypid
gefolgt von
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core

przemek
quelle
3
gcore $pidist auch außerhalb von gdb verfügbar (als kleines Wrapper-Skript)
Tobu
gcore hat keine Möglichkeit, nach / dev / null zu schreiben. Dies ist das, was Sie möchten, wenn Sie versuchen, einen Prozess zurück in den Speicher zu zwingen. Sie können dies jedoch mit einem einzigen Befehl tun: gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
hackerb9
0

Mit swapon / swapoff wird Ihr Swap-Speicherplatz vollständig freigegeben, Sie können jedoch auch einen Teil davon über das / proc-Dateisystem freigeben. Du willst den ersten:

# To free pagecache
echo 1 > /proc/sys/vm/drop_caches

# To free dentries and inodes
echo 2 > /proc/sys/vm/drop_caches

# To free pagecache, dentries and inodes
echo 3 > /proc/sys/vm/drop_caches

über http://linux-mm.org/Drop_Caches

Mark McKinstry
quelle
3
Swap-Speicher ist per Definition kein Cache. Es ist sehr unwahrscheinlich, dass das Löschen der Caches etwas am Swap ändert. Außerdem ist es vorzuziehen, sysctl zu verwenden, anstatt Dateien im proc-Dateisystem direkt zu überschreiben. sysctl vm.drop_caches=X. Außerdem ist sysctl einfacher zu sudo.
Juliano
@ Julian virtuellen Speicher = RAM + Swap Iirc. Sowohl Anwendungen als auch Caches verwenden virtuellen Speicher. Ich denke jedoch, dass die Operation alles außer den Caches aus dem Swap löschen muss , da ich bezweifle, dass das wirklich das ist, was ihn beeinflusst.
Xenoterracide
@xenoterracide: Caches machen nur im realen RAM-Speicher Sinn. Es ist sinnlos, den Cache im Swap zu speichern, sie sind vollkommen gegensätzlich. Swap ist ein langsamer Speicher, der verwendet wird, wenn der physische Arbeitsspeicher des Systems knapp ist . Cache ist schneller Arbeitsspeicher, der verwendet wird, wenn das System über ausreichend nicht verwendeten physischen Arbeitsspeicher verfügt .
Juliano
@juliano ja, ich weiß, aber ich glaube, sie werden beide mit virtuellem Speicher gespeichert, obwohl es möglich ist, dass Caches nur im RAM gespeichert werden. Ehrlich gesagt macht das Löschen der Caches hier keinen Sinn, imo.
Xenoterracide