Chống phân mảnh RAM / OOM


11

Câu hỏi này khá dài, vì vậy tôi sẽ đặt câu hỏi ở đầu và sau đó đi qua phương pháp của tôi để đến với câu hỏi:

  1. Có phải rm (dựa trên Busybox) không thực thi vì không đủ RAM liền kề?
  2. Nếu vậy, có một phương pháp nhẹ để chống phân mảnh DMA - mà không cần dùng đến hệ thống khởi động lại không?
  3. Nếu không, điều gì gây ra nó? Làm thế nào tôi có thể ngăn chặn nó xảy ra trong tương lai?

Sau khi hệ thống kiểm tra của chúng tôi hoạt động khá mạnh trong vài ngày qua - tôi đã telnet vào hệ thống và kiểm tra kết quả kiểm tra. Khi tôi đến để xóa một số dữ liệu, hệ thống trả về dòng lệnh (như thể lệnh đã thực thi đúng). Khi tôi đến để kiểm tra thư mục cho một tập kết quả khác, tôi thấy tệp vẫn tồn tại (sử dụng ls).

Sau này, tôi nhận thấy ngày càng nhiều lệnh shell của mình không hoạt động như mong đợi.

Tôi sẽ bắt đầu với một đầu ra từ dmesg sau khi rm không thực thi đúng:

Phân bổ chiều dài 61440 từ quy trình 6821 (rm) không thành công

DMA mỗi cpu:

CPU 0: hi: 0, btch: 1 usd: 0

Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 không thể mô tả: 6 bẩn: 0 writBack: 0 không ổn định: 0 miễn phí: 821 slab: 353 ánh xạ: 0 pagetables: 0 nảy: 0

DMA miễn phí: 3284kB phút: 360kB thấp: 448kB cao: 540kB active_anon: 0kB inactive_anon: 0kB active_file: 4kB inactive_file: 0kB không thể xác định: 24kB hiện tại: 8128 trang Không

lowmem_reserve []: 0 0 0

DMA: 31 * 4kB 47 * 8kB 42 * 16kB 64 * 32kB 1 * 64kB 0 * 128kB 0 * 256kB 0 * 512kB 0 * 1024kB 0 * 2048kB 0 * 4096kB = 3284kB

Tổng cộng 14 trang pagecache

Không thể phân bổ RAM cho dữ liệu quá trình, errno 12

Ban đầu, tôi nghĩ rằng tôi không thể chạy chương trình trong phần lớn nhất của bộ nhớ liền kề. Có nghĩa là DMA quá phân mảnh và tôi sẽ phải tìm cách để hệ thống chống phân mảnh bộ nhớ.

Sau đó, tôi đã thực hiện kiểm tra toán / vệ sinh nhanh chóng và nhận ra rằng chương trình lẽ ra đã có thể chạy trong khe cắm bộ nhớ liền kề 64kB. Rm đã yêu cầu 61440 byte (60kB).

Tôi đã thực hiện một "chống phân mảnh thủ công" cũ và khởi động lại hệ thống. Khi tôi khởi động lại sytem, ​​tôi xuất / Proc / Buddyinfo:

Node 0, zone DMA 2 8 3 12 0 1 0 1 0 1 0

Mà tôi nghi ngờ bản đồ tới:

  • 2 x 4 kB
  • 8 x 8 kB
  • 3 x 16 kB
  • 12 x 32 kB
  • 1 x 128 kB
  • 1 x 512 kB

Nhưng nếu tổng hợp danh sách các giá trị ở trên, nó không khớp với đầu ra của / Proc / meminfo :

MemTotal:           6580 kB
MemFree:            3164 kB
Buffers:               0 kB
Cached:              728 kB
SwapCached:            0 kB
Active:              176 kB
Inactive:            524 kB
Active(anon):          0 kB
Inactive(anon):        0 kB
Active(file):        176 kB
Inactive(file):      524 kB`
Unevictable:           0 kB
Mlocked:               0 kB
MmapCopy:            844 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                 0 kB
Writeback:             0 kB
AnonPages:             0 kB
Mapped:                0 kB
Slab:               1268 kB
SReclaimable:        196 kB
SUnreclaim:         1072 kB
PageTables:            0 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:        3288 kB
Committed_AS:          0 kB
VmallocTotal:          0 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB

Tóm lại, câu hỏi của tôi là:

  1. Có phải rm không thực thi vì không đủ RAM liền kề?
  2. Nếu vậy, có một phương pháp nhẹ để chống phân mảnh DMA - mà không cần dùng đến hệ thống khởi động lại không?
  3. Nếu không, điều gì gây ra nó? Làm thế nào tôi có thể ngăn chặn nó xảy ra trong tương lai?

Tôi đang sử dụng XPort Pro của Lantronix (8MB, HĐH Linux) chạy phiên bản uClinux 2.6.30. Vỏ đang sử dụng thì im lặng.


Điểm nhỏ: bạn bỏ ra 1 x 2048 kB từ danh sách các khối bộ nhớ. Nếu bạn bao gồm số đó, thì tổng là 3192 kB, rất gần với 3164 kB được liệt kê trong / Proc / meminfo.
Alex Selby

Câu trả lời:


11

Đối với câu hỏi 2 của bạn (bộ nhớ chống phân mảnh), trích dẫn từ https://www.kernel.org/doc/Documentation/sysctl/vm.txt :

compact_memory

Chỉ khả dụng khi CONFIG_COMPACTION được đặt. Khi 1 được ghi vào tệp, tất cả các vùng được nén sao cho bộ nhớ trống có sẵn trong các khối liền kề nếu có thể. Điều này có thể quan trọng, ví dụ như trong việc phân bổ các trang lớn mặc dù các quy trình cũng sẽ trực tiếp thu gọn bộ nhớ theo yêu cầu.

điều này ngụ ý rằng lệnh sau (được thực thi với quyền root và nếu tùy chọn kernel được đề cập ở trên đã được bật)

echo 1 > /proc/sys/vm/compact_memory

nên nói với kernel cố gắng chống phân mảnh bộ nhớ càng nhiều càng tốt. Coi chừng đó là trên một số phiên bản RHEL6, điều này có thể làm sập kernel ...


1
Cảm ơn đã dành thời gian để trở lại và nhận xét về một câu hỏi cũ!
OldTinfoil

7

Mất một chút thời gian, nhưng tôi nghĩ tôi sẽ không trả lời cho đến khi tôi có câu trả lời cho cả 3 câu hỏi phụ của mình.

Trước khi tôi bắt đầu, tôi sẽ đề cập đến thuật ngữ chính xác khi nói đến bộ nhớ làm việc "phân mảnh" được gọi là bộ nhớ làm việc "nén".

1. Có phải rm không thực thi vì không đủ RAM liền kề?

Tôi đã đúng trong kết luận của mình - rm đã không thực thi vì không đủ RAM liền kề. Hệ thống đã được mua RAM và phân mảnh nó, do đó làm cho nó không thể phục hồi.

2. Nếu vậy, có một phương pháp nhẹ để chống phân mảnh DMA - mà không cần dùng đến hệ thống khởi động lại không?

Hóa ra không có cách nào để thu gọn bộ nhớ, thiếu khởi động lại hệ thống nhúng. Trong trường hợp hệ thống không có MMU, phòng ngừa là tên của trò chơi.

Một phần trong tôi suy nghĩ nếu có thể hack kernel linux để mô phỏng MMU trong phần mềm. Tôi nghĩ rằng nếu có thể, ai đó đã làm điều đó rồi. Tôi không thể tưởng tượng nó là một khái niệm hoàn toàn mới;)

3. Làm thế nào tôi có thể ngăn chặn nó xảy ra trong tương lai?

Đối với dự án này, tôi đã sử dụng cron để tự khởi động chương trình mỗi khi được yêu cầu. Một cách tốt hơn để làm điều này là gọi chương trình khi khởi động, và sau đó buộc chương trình ngủ cho đến khi được yêu cầu. Theo cách này, bộ nhớ không cần phải được phân bổ cho mỗi lần sử dụng. Do đó làm giảm sự phân mảnh.

Trong lần lặp đầu tiên của dự án, chúng tôi đã dựa vào các lệnh gọi shell shell của tôi để thực hiện các chức năng quan trọng (như rm). Chúng tôi không thấy sự cần thiết phải phát minh lại bánh xe nếu chúng tôi không cần.

Tuy nhiên, tôi khuyên bạn nên tránh hệ vỏ khi có thể cho hệ thống không có MMU -

( Câu hỏi , điều gì xảy ra nếu bạn thực thi ls -la /path/to/directory/ | grep file-i-seek?)

( Trả lời : nó bắt đầu một quy trình con mới)

Nếu bạn cần triển khai một số chức năng tập lệnh shell shell trong chương trình C của mình, tôi khuyên bạn nên kiểm tra mã nguồn được sử dụng trong BusyBox . Có thể bạn sẽ sử dụng C trong hệ thống nhúng của mình ..


Cảm ơn đã dành thời gian để quay lại và chia sẻ những phát hiện của bạn.
Caleb

3
[Tôi nhận ra điều này đã cũ] Việc mô phỏng MMU rất khó ... Không có MMU, mọi chương trình đều sử dụng trực tiếp các địa chỉ vật lý khi chúng xuất hiện trên bus bộ nhớ. Bạn có thể mô phỏng một cái, nhưng bạn phải chặn mọi truy cập bộ nhớ (giống như MMU thực tế). Hiệu suất sẽ là khủng khiếp. Ngoài ra, bạn có thể sử dụng các con trỏ gián tiếp (như Mac OS Classic đã làm, gọi chúng là "tay cầm"), nhưng sau đó bạn có một API hoàn toàn khó khăn và rất khó khăn khi đối mặt với chế độ tiền chế (Mac OS Classic đã sử dụng đa nhiệm hợp tác) .
derobert

Cảm ơn vì đã trở lại và dành thời gian để viết phản hồi đó. Không biết MacOS classic đã làm điều đó.
OldTinfoil
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.