Як перезавантажити всі запущені програми з підкачки в RAM?


20

Якщо у мого робочого столу не вистачає пам’яті і багато міняється, то я звільняю або вбиваю додаток, витрачаючи оперативну пам’ять. Але після цього всі мої настільні / додатки були помінені в обмін і жахливо повільні, чи знаєте ви спосіб "відмінити" (перезавантажити з місця заміни місця в оперативну пам'ять) мій робочий стіл / програми?


Замість того, щоб відміняти всю систему за допомогою swapon/ swapoff(як підказує прийнята на даний момент відповідь), ви можете скасувати заміну диспетчера дисплеїв та всіх його дітей, скидаючи їх пам’яті процесів (що змушує відміняти). Див. Також "Як змусити процес заміщеного zsh замінити?" На stackoverflow.
zrajm

Відповіді:


16

Якщо у вас дійсно знову доступна оперативна пам’ять, ви можете використовувати цю послідовність (як root):

$ swapoff -a
$ swapon -a

(щоб змусити явний підміна всіх ваших програм)

(якщо припустити, що ви використовуєте Linux)


Навіть якщо ви не зробите IIRC, він перемістить якомога більше даних. Хоча це може пошкодити кеш & спільноту. це іноді корисно.
Maciej Piechotka

19

Наступний швидкий і брудний сценарій python скидає пам'ять процесу на stdout. Це має побічний ефект завантаження будь-якої заміненої сторінки чи картографічного файла. Назвіть це як те, 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
Це серйозно одна з найкрутіших речей, яку я коли-небудь бачив під час обміну стеками. Кудо за публікацію цього! Є так багато хороших самородків, щоб витягнути з цього.
Дан

Я не мав змоги спрацювати цей сценарій. З python 2 виявляється помилка, що значення r [0] занадто велике. На python 3 (після виправлення декількох незначних проблем) я отримую OSError: [Errno 5] Помилка вводу / виводу на фрагменті = 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


3
gcore $pidтакож доступний поза gdb (як невеликий скрипт для обгортки)
Tobu

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 легше судо.
Джуліано

@julian віртуальна пам'ять = ram + swap iirc. І програми, і кеші використовують віртуальну пам'ять. Однак я думаю, що оператору потрібно очистити все, крім кеш-файлів від swap, оскільки я сумніваюся, що саме це впливає на нього.
ксенотеррацид

@xenoterracide: кеші мають сенс лише у реальній пам'яті оперативної пам'яті. Зберігати кеш у свопі безглуздо, вони є повною протилежністю. Зміна є повільна пам'ять, яка використовується, коли система не має фізичної оперативної пам'яті ; кеш-пам'ять - це швидка пам'ять, яка використовується, коли в системі є багато невикористаної фізичної пам'яті .
Джуліано

@juliano так, я знаю, але я вважаю, що вони зберігаються за допомогою віртуальної пам'яті, хоча кеші зберігаються лише в оперативній пам'яті. чесно відкидати кеші тут немає сенсу, imo.
ксенотеррацид
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.