Как перезагрузить все запущенные приложения из пространства подкачки в оперативную память?

20

Если на моем рабочем столе не хватает памяти, и я много перезаписываю, то я освобождаю или убиваю приложение, тратящее мою оперативную память Но после этого все мои десктопы / приложения были поменяны местами и ужасно медленны, знаете ли вы способ «разгрузить» (перезагрузить из пространства подкачки в ОЗУ) мой десктоп / приложения?

Profy
источник
Вместо того, чтобы отменить удаление всей системы с помощью swapon/ swapoff(как предполагает принятый в настоящее время ответ), вы можете отменить удаление диспетчера отображения и всех его дочерних элементов путем сброса их памяти процессов (что вызывает отмену отмены). См. Также «Как заставить замененный процесс zsh поменяться местами?» В stackoverflow.
Зрайм

Ответы:

16

Если у вас действительно достаточно оперативной памяти, вы можете использовать эту последовательность (как root):

$ swapoff -a
$ swapon -a

(для принудительной замены всех ваших приложений)

(при условии, что вы используете Linux)

maxschlepzig
источник
Даже если вы не используете IIRC, он перенесет как можно больше данных. Хотя это может повредить кэш и ко. это иногда полезно.
Мацей Пехотка
19

Следующий быстрый и грязный скрипт на python выводит память процесса в стандартный вывод. Это имеет побочный эффект загрузки любой выгруженной страницы или сопоставленного файла. Назовите это как cat_proc_mem 123 456 789где аргументы - идентификаторы процесса.

Этот скрипт полностью специфичен для Linux. Он может быть адаптирован к другим системам с аналогичной /procструктурой (Solaris?), Но забудьте о его запуске, например, * BSD. Даже в Linux вам может потребоваться изменить определение c_pid_tи значения PTRACE_ATTACHи PTRACE_DETACH. Это сценарий проверки принципа, а не пример хорошего программирования. Используйте на свой риск.

Linux делает память процесса доступной как /proc/$pid/mem. Только определенные диапазоны адресов доступны для чтения. Эти диапазоны можно найти, прочитав информацию отображения памяти из текстового файла /proc/$pid/maps. Псевдофайл /proc/$pid/memне может быть прочитан всеми процессами, которые имеют разрешение на его чтение: должен быть вызван процесс чтения 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)

Смотрите также больше информации о/proc/$pid/mem .

unswap () {
  cat_proc_mem "$@" >/dev/null
}
Жиль "ТАК - перестань быть злым"
источник
2
Это серьезно одна из самых крутых вещей, которые я когда-либо видел при обмене стека. Слава за размещение этого! Есть так много хороших самородков, чтобы извлечь из этого.
Дан
Я не смог заставить этот скрипт работать. С питоном 2 это показывает ошибку, что значение r [0] слишком велико. На питоне 3 (после исправления нескольких незначительных проблем) я получаю OSError: [Errno 5] Ошибка ввода / вывода в chunk = mem_file.read (r [1] - r [0]), и программа, которую я использовал, зависает в обоих случаев.
barteks2x
@ Barteks2x Извините, у меня сейчас нет времени, чтобы сделать этот скрипт защищенным от ошибок. Это работает для меня, по крайней мере, на машинах, которые не имеют слишком много ограничений безопасности (техника использует некоторые интерфейсы отладки, которые отключены на усиленных установках). Программа приостанавливается во время отслеживания, отправьте ей SIGCONT ( kill -CONT 1234где 1234 - PID), чтобы возобновить ее.
Жиль "ТАК - перестань быть злым"
@ Barteks2x: я добавил сюда проверку ошибок . Это заставляет скрипт работать даже на IOErrors из / dev / dri / card0 и OverflowErrors из [vsyscall]. (Это также распечатывает то, что было проблемной областью).
hackerb9
6

Просто для полноты, GDB может создать дамп образа процесса. Я не проверял, что это отменяет его, но это должно - нет другого способа прочитать всю память процесса:
gdb -p $mypid
затем
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core

Przemek
источник
3
gcore $pidтакже доступен за пределами GDB (в виде небольшого скрипта-обёртки)
Тобу,
У gcore нет возможности записать в / dev / null, что вам и нужно, если вы пытаетесь принудительно вернуть процесс обратно в память. Тем не менее, вы можете сделать это в одной команде, например так: gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
hackerb9
0

swapon / swapoff полностью очистит ваше пространство подкачки, но вы также можете освободить его через файловую систему / proc. Вы хотите первый:

# 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

через http://linux-mm.org/Drop_Caches

Марк Маккинстри
источник
3
Память подкачки по определению не кеш. Удаление кешей вряд ли что-то изменит в свопе. Кроме того, предпочтительно использовать sysctl вместо прямой записи файлов в файловой системе proc. sysctl vm.drop_caches=X, Кроме того, sysctl легче sudo.
Джулиано
@julian virtual memory = ram + swap iirc. И приложения, и кеши используют виртуальную память. Однако я думаю, что операционному агенту нужно очистить все, кроме кэшей от свопинга, так как я сомневаюсь, что это действительно то, что на него влияет.
ксенотеррацид
@xenoterracide: кэши имеют смысл только в реальной памяти RAM. Бессмысленно хранить кеш в свопе, они полные противоположности. Swap - медленная память, используемая, когда системе не хватает физической памяти ; Кэш-память - это быстрая память, используемая, когда в системе много неиспользуемой физической памяти .
Джулиано
@juliano Да, я знаю, но я считаю, что они оба хранятся с использованием виртуальной памяти, хотя возможно, что кэши хранятся только в оперативной памяти. честно, сбрасывать тайники здесь не имеет смысла, имо.
ксенотеррацид