Defragging RAM / OOM kegagalan


11

Pertanyaan ini cukup panjang, jadi saya akan mengajukan pertanyaan di atas dan kemudian melanjutkan metode saya untuk datang ke pertanyaan:

  1. Apakah (berbasis Busybox) rm tidak dijalankan karena tidak ada cukup RAM yang berdekatan?
  2. Jika demikian, apakah ada metode ringan defragging DMA - tanpa menggunakan sistem restart?
  3. Jika tidak, apa yang menyebabkannya? Bagaimana saya bisa mencegahnya terjadi di masa depan?

Setelah sistem pengujian kami berjalan cukup intensif selama beberapa hari terakhir - saya telnet ke sistem dan memeriksa hasil pengujian. Ketika saya datang untuk menghapus beberapa data, sistem mengembalikan baris perintah (seolah-olah perintah telah dijalankan dengan benar). Ketika saya datang untuk memeriksa direktori untuk set hasil yang lain, saya melihat file tersebut masih ada (menggunakan ls).

Setelah ini, saya perhatikan semakin banyak perintah shell saya tidak berfungsi seperti yang diharapkan.

Saya akan mulai dengan output dari dmesg setelah rm gagal dieksekusi dengan benar:

Alokasi dengan panjang 61440 dari proses 6821 (rm) gagal

DMA per-CPU:

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

Active_anon: 0 active_file: 1 inactive_anon: 0 inactive_file: 0 unevictable: 6 dirty: 0 writeback: 0 unstable: 0 free: 821 slab: 353 dipetakan: 0 pagetable: 0 bounce: 0

DMA gratis: 3284kB min: 360kB rendah: 448kB tinggi: 540kB aktif_anon: 0kB tidak aktif_anon: 0kB aktif_file: 4kB tidak aktif_file: 0kB tidak dapat ditangguhkan: 24kB sekarang: 8128kB halaman_memindai: 0 all_unreclaimable? tidak

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 * 2096kB 0 * 4096kB = 3284kB

14 total halaman pagecache

Tidak dapat mengalokasikan RAM untuk memproses data, errno 12

Awalnya, saya pikir saya tidak dapat menjalankan program di bagian terbesar dari memori yang berdekatan. Berarti DMA terlalu terfragmentasi dan saya harus menemukan cara untuk mendapatkan sistem untuk mendefrag memori.

Kemudian saya melakukan pemeriksaan matematika / kewarasan cepat dan menyadari bahwa program seharusnya bisa berjalan di slot memori berdekatan 64kB tunggal. Rm meminta 61440 byte (60kB).

Saya melakukan "defrag manual" lama yang baik dan mem-boot ulang sistem. Ketika saya reboot sistem saya output / proc / buddyinfo:

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

Yang saya duga peta untuk:

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

Tetapi jika seseorang menjumlahkan daftar nilai di atas, itu tidak cocok dengan output dari / 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

Untuk rekap, pertanyaan saya adalah:

  1. Apakah saya tidak menjalankan karena tidak ada cukup RAM yang berdekatan?
  2. Jika demikian, apakah ada metode ringan defragging DMA - tanpa menggunakan sistem restart?
  3. Jika tidak, apa yang menyebabkannya? Bagaimana saya bisa mencegahnya terjadi di masa depan?

Saya menggunakan Lantortix's XPort Pro (8MB, Linux OS) menjalankan uClinux versi 2.6.30. Shell yang digunakan diam.


Poin minor: Anda kehabisan 1 x 2048 kB dari daftar memori Anda. Jika Anda memasukkannya, maka jumlahnya adalah 3192 kB yang sangat dekat dengan 3164 kB yang terdaftar di / proc / meminfo.
Alex Selby

Jawaban:


11

Pada pertanyaan Anda 2 (defragmenting memory), mengutip dari https://www.kernel.org/doc/Documentation/sysctl/vm.txt :

compact_memory

Hanya tersedia ketika CONFIG_COMPACTION diatur. Ketika 1 ditulis ke file, semua zona dipadatkan sedemikian sehingga memori bebas tersedia di blok yang berdekatan jika memungkinkan. Ini dapat menjadi penting misalnya dalam alokasi halaman besar meskipun proses juga akan secara langsung memadatkan memori sebagaimana diperlukan.

ini menyiratkan bahwa perintah berikut (dijalankan dengan hak akses root dan jika opsi kernel yang disebutkan di atas diaktifkan)

echo 1 > /proc/sys/vm/compact_memory

harus memberitahu kernel untuk mencoba mendefrag memori sebanyak mungkin. Hati-hati, mis. Pada beberapa versi RHEL6, ini dapat membuat kernel ...


1
Terima kasih telah meluangkan waktu untuk kembali dan mengomentari pertanyaan lama!
OldTinfoil

7

Butuh sedikit waktu, tetapi saya pikir saya akan menunda menjawab sampai saya punya jawaban untuk semua 3 sub-pertanyaan saya.

Sebelum saya mulai, saya akan menyebutkan bahwa istilah yang benar ketika datang ke "de-fragmenting" memori kerja disebut dengan "memadatkan" memori kerja.

1. Apakah rm tidak dieksekusi karena tidak ada cukup RAM yang berdekatan?

Saya benar dalam kesimpulan saya - rm tidak mengeksekusi karena ada cukup RAM yang berdekatan. Sistem telah memperoleh RAM dan memecah-mecahnya, sehingga membuatnya tidak dapat diklaim kembali.

2. Jika demikian, apakah ada metode ringan defragging DMA - tanpa menggunakan sistem restart?

Ternyata tidak ada cara memadatkan memori, singkat untuk memulai ulang sistem tertanam. Dalam kasus sistem tanpa-MMU, pencegahan adalah nama permainan.

Sebagian dari saya merenungkan apakah mungkin untuk meretas kernel linux untuk meniru MMU dalam perangkat lunak. Saya pikir jika itu mungkin, seseorang pasti sudah melakukannya. Saya tidak bisa membayangkan itu konsep yang sama sekali baru;)

3. Bagaimana saya bisa mencegahnya terjadi di masa depan?

Untuk proyek ini, saya menggunakan cron untuk memulai program secara manual setiap kali diperlukan. Cara yang lebih baik untuk melakukan ini adalah dengan memanggil program saat start up, dan kemudian memaksa program untuk tidur sampai diperlukan. Dengan cara ini, memori tidak perlu dialokasikan pada setiap penggunaan. Sehingga mengurangi fragmentasi.

Pada iterasi pertama dari proyek, kami mengandalkan panggilan skrip shell saya untuk melakukan fungsi kritis (seperti rm). Kami tidak melihat perlunya menciptakan kembali roda jika tidak perlu.

Namun, saya akan merekomendasikan menghindari shell jika memungkinkan untuk sistem MMU-kurang -

( Pertanyaan , apa yang terjadi jika Anda mengeksekusi ls -la /path/to/directory/ | grep file-i-seek?)

( Jawab : ini memulai subproses baru)

Jika Anda perlu menerapkan beberapa fungsionalitas skrip shell inti dalam program C Anda, saya sarankan memeriksa kode sumber yang digunakan dalam BusyBox . Kemungkinannya adalah Anda akan menggunakan C di sistem embedded Anda ..


Terima kasih telah meluangkan waktu untuk kembali dan membagikan temuan Anda.
Caleb

3
[Saya sadar ini sudah tua] Meniru MMU itu sulit ... Tanpa MMU, setiap program langsung menggunakan alamat fisik seperti yang muncul di bus memori. Anda bisa meniru satu, tetapi Anda harus mencegat setiap akses memori (seperti halnya MMU yang sebenarnya). Performa akan mengerikan. Atau, Anda dapat menggunakan pointer tidak langsung (seperti yang dilakukan Mac OS Classic, menyebutnya "handle"), tetapi kemudian Anda memiliki API yang benar-benar sulit, dan yang sangat sulit dalam menghadapi pre-emption (Mac OS Classic menggunakan multitasking kooperatif) .
derobert

Terima kasih telah kembali dan meluangkan waktu untuk menulis tanggapan itu. Tidak tahu MacOS classic melakukan itu.
OldTinfoil
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.