Làm cách nào để tải lại tất cả các ứng dụng đang chạy từ không gian hoán đổi vào RAM?


20

Nếu máy tính để bàn của tôi hết bộ nhớ và hoán đổi nhiều thì tôi giải phóng hoặc giết ứng dụng làm lãng phí RAM của tôi. Nhưng, sau đó, tất cả máy tính để bàn / ứng dụng của tôi đã bị tráo đổi và chậm kinh khủng, bạn có biết cách "unswap" (tải lại từ không gian hoán đổi vào RAM) máy tính để bàn / ứng dụng của tôi không?


Thay vì hủy kết nối toàn bộ hệ thống bằng cách sử dụng swapon/ swapoff(như câu trả lời hiện được chấp nhận cho thấy), bạn có thể muốn hủy bỏ trình quản lý hiển thị của mình và tất cả các con của nó bằng cách bỏ các ký ức quá trình của chúng (bắt buộc bỏ qua). Xem thêm Cách làm thế nào để buộc một quá trình zsh hoán đổi để hoán đổi trong? Vượt trên stackoverflow.
zrajm

Câu trả lời:


16

Nếu bạn thực sự có đủ RAM có sẵn một lần nữa, bạn có thể sử dụng chuỗi này (với quyền root):

$ swapoff -a
$ swapon -a

(để buộc trao đổi rõ ràng tất cả các ứng dụng của bạn)

(giả sử rằng bạn đang sử dụng linux)


Ngay cả khi bạn không IIRC, nó sẽ di chuyển càng nhiều dữ liệu càng tốt. Trong khi nó có thể làm hỏng bộ nhớ cache & co. nó đôi khi hữu ích
Maciej Piechotka

18

Kịch bản python nhanh và bẩn sau đây đưa bộ nhớ của một tiến trình vào thiết bị xuất chuẩn. Điều này có tác dụng phụ là tải bất kỳ trang bị hoán đổi hoặc tệp ánh xạ. Gọi nó là cat_proc_mem 123 456 789nơi các đối số là ID quá trình.

Kịch bản này là hoàn toàn cụ thể cho Linux. Nó có thể thích ứng với các hệ thống khác có /proccấu trúc tương tự (Solaris?), Nhưng quên đi việc chạy nó trên ví dụ * BSD. Ngay cả trên Linux, bạn có thể cần thay đổi định nghĩa c_pid_tvà các giá trị của PTRACE_ATTACHPTRACE_DETACH. Đây là một kịch bản chứng minh nguyên tắc, không có nghĩa là một ví dụ về thực hành lập trình tốt. Sử dụng có nguy cơ của riêng bạn.

Linux làm cho bộ nhớ của một quá trình có sẵn như /proc/$pid/mem. Chỉ có phạm vi địa chỉ nhất định là có thể đọc được. Những phạm vi này có thể được tìm thấy bằng cách đọc thông tin ánh xạ bộ nhớ từ tệp văn bản /proc/$pid/maps. Tệp giả /proc/$pid/memcó thể được đọc bởi tất cả các quy trình có quyền đọc nó: quá trình đọc phải được gọi 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)

Xem thêm thông tin về/proc/$pid/mem .

unswap () {
  cat_proc_mem "$@" >/dev/null
}

2
Đây thực sự là một trong những điều tuyệt vời nhất tôi từng thấy trên sàn giao dịch stack. Kudos cho đăng bài này! Có rất nhiều cốm tốt để kéo từ này.
Dan

Thật không may, tôi đã không thể làm cho kịch bản này hoạt động. Với python 2, nó hiển thị lỗi rằng giá trị r [0] quá lớn. Trên python 3 (sau khi sửa một vài vấn đề nhỏ) tôi gặp OSError: [Errno 5] Lỗi đầu vào / đầu ra tại chunk = mem_file.read (r [1] - r [0]) và chương trình tôi đã sử dụng bị treo ở cả hai các trường hợp.
barteks2x

@ Barteks2x Tôi xin lỗi, tôi không có thời gian để làm cho kịch bản này không bị lỗi. Nó hoạt động với tôi, ít nhất là trên các máy không có quá nhiều hạn chế bảo mật (kỹ thuật sử dụng một số giao diện gỡ lỗi bị vô hiệu hóa trên các thiết lập cứng). Chương trình bị treo trong khi nó đang được theo dõi, hãy gửi cho nó một SIGCONT ( kill -CONT 1234trong đó 1234 là PID) để tiếp tục chương trình.
Gilles 'SO- ngừng trở thành ác quỷ'

@ Barteks2x: Tôi đã thêm một số kiểm tra lỗi ở đây . Điều này làm cho tập lệnh hoạt động ngay cả trên IOErrors từ / dev / Dri / card0 và OverflowErrors từ [vsyscall]. (Nó cũng in ra khu vực có vấn đề).
hackerb9

6

Chỉ cần cho đầy đủ, GDB có thể kết xuất hình ảnh quá trình. Tôi đã không kiểm tra xem nó có giải phóng nó không, nhưng nó phải --- không có cách nào khác để đọc toàn bộ bộ nhớ quá trình:
gdb -p $mypid
tiếp theo là
(gdb) gcore /tmp/myprocess-core
Saved corefile /tmp/myprocess-core


3
gcore $pidcũng có sẵn bên ngoài gdb (dưới dạng tập lệnh bao bọc nhỏ)
Tobu

gcore không có cách nào để ghi vào / dev / null, đó là những gì bạn muốn nếu bạn đang cố gắng đưa một quá trình trở lại bộ nhớ. Tuy nhiên, bạn có thể thực hiện nó trong một lệnh duy nhất như vậy: gdb --batch -p $pid -ex "gcore /dev/null" 2>/dev/null
hackerb9

0

hoán đổi / hoán đổi sẽ xóa hoàn toàn không gian hoán đổi của bạn, nhưng bạn cũng có thể giải phóng một phần của nó thông qua hệ thống tệp / Proc. Bạn muốn cái đầu tiên:

# 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

thông qua http://linux-mm.org/Drop_Caches


3
Theo định nghĩa, bộ nhớ hoán đổi không phải là bộ nhớ cache. Bỏ bộ nhớ cache là rất khó có thể thay đổi bất cứ điều gì trong trao đổi. Ngoài ra, tốt hơn là sử dụng sysctl thay vì ghi trực tiếp lên các tệp trong hệ thống tệp Proc. sysctl vm.drop_caches=X. Ngoài ra, sysctl dễ dàng hơn để sudo.
Juliano

@julian bộ nhớ ảo = ram + hoán đổi iirc. Cả ứng dụng và bộ nhớ cache đều sử dụng bộ nhớ ảo. Tuy nhiên tôi nghĩ rằng các op cần phải xóa tất cả mọi thứ trừ bộ đệm từ trao đổi, vì tôi nghi ngờ đó là những gì thực sự ảnh hưởng đến anh ta.
xenoterracide

@xenoterracide: cache chỉ có ý nghĩa trong bộ nhớ RAM thực. Việc lưu trữ bộ đệm trong trao đổi là vô nghĩa, chúng hoàn toàn đối lập. Hoán đổi là bộ nhớ chậm được sử dụng khi hệ thống thiếu RAM vật lý ; bộ nhớ cache là bộ nhớ nhanh được sử dụng khi hệ thống có nhiều RAM vật lý không sử dụng .
Juliano

@juliano vâng tôi biết, nhưng tôi tin rằng cả hai đều được lưu trữ bằng bộ nhớ ảo, mặc dù có thể bộ nhớ cache chỉ được lưu trữ trong RAM. Thành thật thả bộ nhớ cache không có ý nghĩa ở đây, imo.
xenoterracide
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.