Bagaimana cara memuat ulang semua aplikasi yang berjalan dari ruang swap ke RAM?

20

Jika desktop saya kehabisan memori dan banyak bertukar maka saya membebaskan atau mematikan aplikasi yang membuang-buang RAM saya. Tetapi, setelah itu, semua desktop / aplikasi saya telah ditukar dan sangat lambat, apakah Anda tahu cara "unswap" (memuat ulang dari ruang swap ke RAM) desktop / aplikasi saya?

profy
sumber
Daripada membuka-bongkar seluruh sistem menggunakan swapon/ swapoff(seperti jawaban yang diterima saat ini menyarankan), Anda mungkin ingin membuka-bongkar display manager Anda dan semua anak-anaknya dengan membuang memori proses mereka (yang memaksa unswapping). Lihat juga “Bagaimana cara memaksa proses zsh swapping-out untuk bertukar?” Di stackoverflow.
zrajm

Jawaban:

16

Jika Anda benar-benar memiliki cukup RAM yang tersedia lagi, Anda dapat menggunakan urutan ini (sebagai root):

$ swapoff -a
$ swapon -a

(untuk memaksa swap-in eksplisit semua aplikasi Anda)

(dengan asumsi Anda menggunakan linux)

maxschlepzig
sumber
Bahkan jika Anda tidak IIRC itu akan memindahkan data sebanyak mungkin. Meskipun dapat merusak cache & co. terkadang bermanfaat.
Maciej Piechotka
19

Skrip python cepat dan kotor berikut ini membuang memori suatu proses ke stdout. Ini memiliki efek samping dari memuat halaman yang ditukar atau file yang dipetakan. Sebut saja cat_proc_mem 123 456 789tempat argumennya adalah ID proses.

Skrip ini sepenuhnya khusus untuk Linux. Mungkin dapat beradaptasi dengan sistem lain dengan /procstruktur yang sama (Solaris?), Tetapi lupakan tentang menjalankannya pada misalnya * BSD. Bahkan di Linux, Anda mungkin perlu mengubah definisi c_pid_tdan nilai-nilai PTRACE_ATTACHdan PTRACE_DETACH. Ini adalah skrip pembuktian prinsip, tidak dimaksudkan sebagai contoh praktik pemrograman yang baik. Gunakan dengan risiko Anda sendiri.

Linux membuat memori dari suatu proses tersedia sebagai /proc/$pid/mem. Hanya rentang alamat tertentu yang dapat dibaca. Rentang ini dapat ditemukan dengan membaca informasi pemetaan memori dari file teks /proc/$pid/maps. File pseudo /proc/$pid/memtidak dapat dibaca oleh semua proses yang memiliki izin untuk membacanya: proses pembaca harus memanggil 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)

Lihat juga informasi lebih lanjut tentang/proc/$pid/mem .

unswap () {
  cat_proc_mem "$@" >/dev/null
}
Gilles 'SANGAT berhenti menjadi jahat'
sumber
2
Ini benar-benar salah satu hal paling keren yang pernah saya lihat di stack stack. Kudos untuk memposting ini! Ada begitu banyak nugget yang menarik dari ini.
Dan
Sayangnya, saya tidak dapat mengaktifkan skrip ini. Dengan python 2 itu menunjukkan kesalahan bahwa nilai r [0] terlalu besar. Pada python 3 (setelah memperbaiki beberapa masalah kecil) saya mendapatkan OSError: [Errno 5] Kesalahan input / output di chunk = mem_file.read (r [1] - r [0]) dan program yang saya gunakan pada hang di keduanya kasus.
barteks2x
@ Barteks2x Maaf, saya tidak punya waktu sekarang untuk membuat skrip ini tahan kesalahan. Ini berhasil bagi saya, setidaknya pada mesin yang tidak memiliki terlalu banyak batasan keamanan (teknik ini menggunakan beberapa antarmuka debugging yang dinonaktifkan pada pengaturan yang diperkeras). Program ini ditangguhkan saat sedang dilacak, kirimkan sebuah SIGCONT (di kill -CONT 1234mana 1234 adalah PID) untuk melanjutkannya.
Gilles 'SANGAT berhenti menjadi jahat'
@ Barteks2x: Saya telah menambahkan beberapa pengecekan error di sini . Ini membuat skrip bekerja bahkan pada IOErrors dari / dev / dri / card0 dan OverflowErrors dari [vsyscall]. (Ini juga mencetak apa area masalahnya).
hackerb9
6

Hanya untuk kelengkapan, GDB dapat membuang gambar proses. Saya tidak memeriksa apakah itu membuka, tetapi harus --- tidak ada cara lain untuk membaca seluruh memori proses:
gdb -p $mypid
diikuti oleh
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core

przemek
sumber
3
gcore $pidjuga tersedia di luar gdb (sebagai skrip pembungkus kecil)
Tobu
gcore tidak memiliki cara untuk menulis ke / dev / null, yang Anda inginkan jika Anda mencoba untuk memaksa suatu proses kembali ke memori. Namun, Anda dapat melakukannya dalam satu perintah seperti ini: gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
hackerb9
0

swapon / swapoff akan sepenuhnya menghapus ruang swap Anda, tetapi Anda dapat mengosongkannya melalui sistem file / proc juga. Anda ingin yang pertama:

# 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

via http://linux-mm.org/Drop_Caches

Mark McKinstry
sumber
3
Swap memory, menurut definisi, bukan cache. Menjatuhkan cache sangat tidak mungkin untuk mengubah apa pun di swap. Juga, lebih baik menggunakan sysctl daripada langsung menulis di atas file dalam sistem file proc. sysctl vm.drop_caches=X. Juga, sysctl lebih mudah untuk sudo.
Juliano
@julian virtual memory = ram + swap iirc. Baik aplikasi dan cache menggunakan memori virtual. Namun saya berpikir bahwa op perlu menghapus semuanya kecuali cache dari swap, karena saya ragu itu benar-benar apa yang mempengaruhinya.
xenoterracide
@xenoterracide: cache hanya masuk akal dalam memori RAM yang nyata. Tidak ada gunanya untuk menyimpan cache dalam swap, mereka sepenuhnya bertentangan. Swap adalah memori lambat yang digunakan ketika sistem kekurangan RAM fisik ; cache adalah memori cepat yang digunakan ketika sistem memiliki banyak RAM fisik yang tidak digunakan .
Juliano
@ juliano ya saya tahu, tapi saya percaya mereka berdua disimpan menggunakan memori virtual, meskipun mungkin saja cache hanya bisa disimpan dalam RAM. jujur ​​menjatuhkan cache tidak masuk akal di sini, imo.
xenoterracide