GNU/Linux >> Belajar Linux >  >> Linux

Situasi oom Linux (kernel 32 bit)

Solusi 1:

Namun, pendekatan 'palu godam' adalah memutakhirkan ke O/S 64bit (ini adalah 32bit) karena tata letak zona dilakukan secara berbeda.

Oke jadi disini saya akan mencoba menjawab kenapa anda mengalami OOM disini. Ada sejumlah faktor yang berperan di sini.

  • Ukuran pesanan permintaan dan cara kernel memperlakukan ukuran pesanan tertentu.
  • Zona sedang dipilih.
  • Tanda air yang digunakan zona ini.
  • Fragmentasi dalam zona.

Jika Anda melihat OOM itu sendiri, jelas ada banyak memori kosong yang tersedia tetapi OOM-killer dipanggil? Mengapa?

Ukuran pesanan permintaan dan bagaimana kernel memperlakukan ukuran pesanan tertentu

Kernel mengalokasikan memori berdasarkan pesanan. 'Pesanan' adalah wilayah RAM yang berdekatan yang harus dipenuhi agar permintaan berfungsi. Urutan disusun berdasarkan urutan besarnya (demikian nama urutannya) menggunakan algoritme 2^(ORDER + 12) . Jadi, urutan 0 adalah 4096, urutan 1 adalah 8192, urutan 2 adalah 16384 dan seterusnya.

Kernel memiliki nilai kode keras dari apa yang dianggap sebagai 'urutan tinggi' (> PAGE_ALLOC_COSTLY_ORDER ). Ini adalah urutan 4 dan lebih tinggi (64kb atau lebih tinggi adalah urutan tinggi).

Pesanan tinggi dipenuhi untuk alokasi halaman secara berbeda dari pesanan rendah. Alokasi pesanan tinggi jika gagal mengambil memori, pada kernel modern akan melakukannya.

  • Coba jalankan memori rutin pemadatan untuk mendefrag memori.
  • Tidak pernah panggil OOM-killer untuk memenuhi permintaan.

Ukuran pesanan Anda tercantum di sini

Dec 27 09:19:05 2013 kernel: : [277622.359064] squid invoked oom-killer: gfp_mask=0x42d0, order=3, oom_score_adj=0

Urutan 3 adalah yang tertinggi dari permintaan urutan rendah dan (seperti yang Anda lihat) memanggil OOM-killer dalam upaya untuk memenuhinya.

Perhatikan bahwa sebagian besar alokasi ruang pengguna tidak menggunakan permintaan tingkat tinggi. Biasanya itu adalah kernel yang membutuhkan wilayah memori yang berdekatan. Pengecualian untuk hal ini mungkin terjadi saat ruang pengguna menggunakan halaman besar - tetapi tidak demikian halnya di sini.

Dalam kasus Anda, alokasi pesanan 3 dipanggil oleh kernel yang ingin mengantri paket ke tumpukan jaringan - membutuhkan alokasi 32 kb untuk melakukannya.

Zona sedang dipilih.

Kernel membagi wilayah memori Anda menjadi beberapa zona. Pemotongan ini dilakukan karena pada x86 wilayah memori tertentu hanya dapat dialamatkan oleh perangkat keras tertentu. Perangkat keras lama mungkin hanya dapat menangani memori di zona 'DMA' misalnya. Saat kita ingin mengalokasikan sebagian memori, pertama zona dipilih dan hanya memori bebas dari zona ini diperhitungkan saat membuat keputusan alokasi.

Meskipun saya tidak sepenuhnya memiliki pengetahuan tentang algoritme pemilihan zona, kasus penggunaan umumnya adalah tidak pernah mengalokasikan dari DMA, tetapi biasanya memilih zona terendah yang dapat dialamatkan yang dapat memenuhi permintaan.

Banyak informasi zona yang keluar selama OOM yang juga dapat diperoleh dari /proc/zoneinfo .

Dec 27 09:19:05 2013 kernel: : [277622.359382] DMA free:2332kB min:36kB low:44kB high:52kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15968kB managed:6960kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:8kB slab_unreclaimable:288kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
Dec 27 09:19:05 2013 kernel: : [277622.359393] Normal free:114488kB min:3044kB low:3804kB high:4564kB active_anon:0kB inactive_anon:0kB active_file:252kB inactive_file:256kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:894968kB managed:587540kB mlocked:0kB dirty:0kB writeback:0kB mapped:4kB shmem:0kB slab_reclaimable:117712kB slab_unreclaimable:138616kB kernel_stack:11976kB pagetables:0kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:982 all_unreclaimable? yes
Dec 27 09:19:05 2013 kernel: : [277622.359404] HighMem free:27530668kB min:512kB low:48272kB high:96036kB active_anon:2634060kB inactive_anon:217596kB active_file:4688452kB inactive_file:1294168kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:36828872kB managed:36828872kB mlocked:0kB dirty:0kB writeback:0kB mapped:183132kB shmem:39400kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:430856kB unstable:0kB bounce:367564104kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no

Zona yang Anda miliki, DMA, Normal, dan HighMem menunjukkan platform 32-bit, karena zona HighMem tidak ada di 64bit. Juga pada sistem 64bit Normal dipetakan ke 4GB dan seterusnya sedangkan pada 32bit dipetakan hingga 896Mb (walaupun, dalam kasus Anda, kernel melaporkan hanya mengelola porsi yang lebih kecil dari ini:- managed:587540kB .)

Mungkin untuk mengetahui dari mana alokasi ini berasal dengan melihat baris pertama lagi, gfp_mask=0x42d0 memberitahu kita apa jenis alokasi dilakukan. Byte terakhir (0) memberi tahu kita bahwa ini adalah alokasi dari zona normal. Arti gfp terletak di include/linux/gfp.h.

Tanda air yang digunakan zona ini.

Saat memori hampir habis, tindakan untuk mengklaimnya kembali ditentukan oleh tanda air. Mereka muncul di sini:min:3044kB low:3804kB high:4564kB . Jika memori kosong mencapai 'rendah', maka pertukaran akan terjadi hingga kita melewati ambang 'tinggi'. Jika memori mencapai 'min', kita perlu mematikan sesuatu untuk mengosongkan memori melalui OOM-killer.

Fragmentasi dalam zona.

Untuk melihat apakah permintaan untuk urutan memori tertentu dapat dipenuhi, kernel memperhitungkan berapa banyak halaman gratis dan tersedia untuk setiap pesanan. Ini dapat dibaca di /proc/buddyinfo . Laporan OOM-killer juga memuntahkan info sobat seperti yang terlihat di sini:

Normal: 5360*4kB (UEM) 3667*8kB (UEM) 3964*16kB (UEMR) 13*32kB (MR) 0*64kB 1*128kB (R) 1*256kB (R) 0*512kB 0*1024kB 0*2048kB 0*4096kB = 115000kB

Agar alokasi memori terpenuhi, ada harus menjadi memori bebas yang tersedia dalam ukuran pesanan yang diminta atau alokasi yang lebih tinggi. Memiliki banyak dan banyak data gratis dalam urutan rendah dan tidak ada dalam urutan yang lebih tinggi berarti memori Anda terfragmentasi. Jika Anda mendapatkan alokasi pesanan yang sangat tinggi, mungkin (bahkan dengan banyak memori bebas) untuk itu tidak dapat dipenuhi karena tidak ada halaman pesanan tinggi yang tersedia. Kernel dapat mendefrag memori (ini disebut pemadatan memori) dengan memindahkan banyak halaman dengan urutan rendah agar tidak meninggalkan celah di ruang ram yang dapat dialamatkan.

Pembunuh OOM dipanggil? Mengapa?

Jadi, jika kita mempertimbangkan hal-hal ini, kita dapat mengatakan yang berikut;

  • Alokasi bersebelahan 32kB dicoba. Dari zona normal.
  • Ada cukup memori kosong di zona yang dipilih.
  • Tersedia memori urutan 3, 5 dan 6 13*32kB (MR) 1*128kB (R) 1*256kB (R)

Jadi, jika ada membebaskan memori, pesanan lain bisa memenuhi permintaan. apa yang terjadi?

Nah, ada lebih banyak untuk mengalokasikan dari pesanan daripada hanya memeriksa jumlah memori bebas yang tersedia untuk pesanan itu atau lebih tinggi. Kernel secara efektif mengurangi memori dari semua urutan yang lebih rendah dari total baris bebas dan kemudian melakukan pemeriksaan tanda air minimum pada apa yang tersisa.

Apa yang terjadi dalam kasus Anda adalah memeriksa memori bebas kami untuk zona yang harus kami lakukan.

115000 - (5360*4) - (3667*8) - (3964*16) = 800

Jumlah memori bebas ini dicocokkan dengan min tanda air, yaitu 3044. Jadi, secara teknis -- Anda tidak memiliki memori bebas tersisa untuk melakukan alokasi yang Anda minta. Dan inilah mengapa Anda memanggil OOM-killer.

Memperbaiki

Ada dua perbaikan. Memutakhirkan ke 64bit mengubah partisi zona Anda sedemikian rupa sehingga 'Normal' adalah 4GB hingga 36GB, jadi Anda tidak akan 'melakukan default' pada alokasi memori Anda ke dalam zona yang bisa sangat terfragmentasi. Bukan karena Anda memiliki lebih banyak memori yang dapat dialamatkan yang memperbaiki masalah ini (karena Anda sudah menggunakan PAE), hanya saja zona yang Anda pilih memiliki lebih banyak memori yang dapat dialamatkan.

Cara kedua (yang belum pernah saya uji) adalah mencoba membuat kernel memadatkan memori Anda secara lebih agresif.

Jika Anda mengubah nilai vm.extfrag_threshold dari 500 hingga 100, ini lebih mungkin untuk memadatkan memori dalam upaya untuk menghormati alokasi tingkat tinggi. Meskipun, saya belum pernah mengotak-atik nilai ini sebelumnya - ini juga akan bergantung pada indeks fragmentasi Anda yang tersedia di /sys/kernel/debug/extfrag/extfrag_index . Saat ini saya tidak memiliki kotak dengan kernel yang cukup baru untuk melihat apa yang ditampilkan untuk menawarkan lebih dari ini.

Alternatifnya, Anda dapat menjalankan semacam tugas cron (ini sangat, sangat jelek) untuk memadatkan memori secara manual dengan menulis ke /proc/sys/vm/compact_memory .

Sejujurnya, saya tidak berpikir ada cara untuk menyetel sistem untuk menghindari masalah ini - sifat pengalokasi memori untuk bekerja dengan cara ini. Mengubah arsitektur platform yang Anda gunakan mungkin merupakan satu-satunya solusi yang dapat diselesaikan secara fundamental.

Solusi 2:

Dari awal:Anda harus benar-benar gunakan sistem operasi 64-bit. Apakah Anda punya alasan bagus untuk tetap menggunakan 32-bit di sini?

Sulit untuk mendiagnosis masalah ini tanpa melihat sistem lebih dekat, lebih disukai sekitar waktu gagal, jadi posting (cepat) saya kurang lebih secara umum ditujukan untuk masalah memori pada sistem 32-bit. Apakah saya menyebutkan menggunakan 64-bit akan menghilangkan semua ini?

Masalah Anda tiga kali lipat.

Pertama-tama, bahkan pada kernel PAE, ruang alamat per proses dibatasi hingga 4GiB[1]. Ini berarti instans squid Anda tidak akan pernah bisa memakan lebih dari 4GiB RAM per proses. Saya tidak terlalu paham dengan squid, tetapi jika ini adalah server proxy utama Anda, itu mungkin tidak cukup.

Kedua, pada sistem 32-bit dengan jumlah RAM yang besar, banyak memori yang disebut 'ZONE_NORMAL' digunakan untuk menyimpan struktur data yang diperlukan untuk menggunakan memori di ZONE_HIGHMEM. Struktur data ini tidak dapat dipindahkan ke ZONE_HIGHMEM sendiri, karena memori yang digunakan kernel untuk tujuannya sendiri harus selalu dalam ZONE_NORMAL (yaitu dalam 1GiB-ish pertama). Semakin banyak memori yang Anda miliki di ZONE_HIGHMEM (banyak, dalam kasus Anda), semakin menjadi masalah, karena kernel membutuhkan lebih banyak memori dari ZONE_NORMAL untuk mengelola ZONE_HIGHMEM. Saat jumlah memori kosong di ZONE_NORMAL mengering, sistem Anda mungkin gagal pada beberapa tugas, karena ZONE_NORMAL adalah tempat banyak hal-hal terjadi pada sistem 32-bit. Semua operasi memori terkait kernel, misalnya;)

Ketiga, bahkan jika ada sisa memori di ZONE_NORMAL (saya belum membaca log Anda secara mendetail), beberapa operasi memori akan membutuhkan memori yang tidak terfragmentasi. Misalnya, jika semua memori Anda terfragmentasi menjadi bagian yang sangat kecil, beberapa operasi yang membutuhkan lebih dari itu akan gagal. [3] Tinjauan singkat pada log Anda memang menunjukkan jumlah fragmentasi yang cukup signifikan di ZONE_DMA dan ZONE_NORMAL.

Sunting:Jawaban Mlfe di atas memiliki penjelasan yang sangat bagus tentang cara kerjanya secara mendetail.

Sekali lagi:pada sistem 64-bit, semua memori ada di ZONE_NORMAL. Tidak ada zona HIGHMEM pada sistem 64-bit. Masalah terpecahkan.

Sunting:Anda dapat melihat di sini [4] untuk melihat apakah Anda dapat memberi tahu oom-killer untuk membiarkan proses penting Anda sendiri. Itu tidak akan menyelesaikan semuanya (jika ada), tetapi mungkin patut dicoba.

[1] http://en.wikipedia.org/wiki/Physical_address_extension#Design

[2] http://www.redhat.com/archives/rhelv5-list/2008-September/msg00237.html dan https://access.redhat.com/site/documentation/en-US/Red_Hat_Enterprise_Linux/5/html /Tuning_and_Optimizing_Red_Hat_Enterprise_Linux_for_Oracle_9i_and_10g_Databases/sect-Oracle_9i_and_10g_Tuning_Guide-Hardware_Architectures_and_Linux_Kernels-a32_bit_Architecture_and_the_hugemem_Kernel.html

[3] http://bl0rg.krunch.be/oom-frag.html

[4] http://lwn.net/Articles/317814/

Solusi 3:

@MIfe telah memberikan tulisan yang sangat baik tentang bagaimana alokasi memori dalam kernel ditangani dan juga memberi Anda solusi yang tepat seperti beralih ke OS 64-bit dan hack jahat seperti pemadatan memori manual melalui /proc/sys/vm/compact_memory di cron .

2 sen saya akan menjadi solusi lain yang dapat membantu Anda:
Saya perhatikan Anda memiliki tcp_tso_segment di backtrace kernel Anda, lakukan juga:

# ethtool -K ethX tso off gso off lro off

dapat menurunkan tekanan pada mm dengan memaksanya menggunakan perintah yang lebih rendah.

PS . daftar semua offload dapat diperoleh melalui # ethtool -k ethX

Solusi 4:

Kepanikannya adalah karena sysctl "vm.panic_on_oom =1" disetel -- idenya adalah me-reboot sistem akan mengembalikannya ke keadaan waras. Anda dapat mengubahnya di sysctl.conf.

Tepat di atas kita membaca cumi-cumi yang dipanggil oom killer. Anda dapat memeriksa konfigurasi squid Anda dan penggunaan memori maksimumnya (atau cukup pindah ke OS 64-bit).

/proc/meminfo menunjukkan zona memori tinggi sedang digunakan, jadi Anda menjalankan kernel 32-bit dengan memori 36GB. Anda juga dapat melihat bahwa di zona normal, untuk memenuhi permintaan memori squid, kernel memindai 982 halaman tanpa hasil:

pages_scanned:982 all_unreclaimable? yes

Linux
  1. Kernel Linux Untuk Nintendo Wii?

  2. Bagaimana kernel Linux menentukan urutan panggilan __init?

  3. Bagaimana saya tahu jika kernel linux saya berjalan di 32bit atau 64bit?

  1. Siklus hidup pengujian kernel Linux

  2. Cara memutakhirkan Kernel di Desktop Linux

  3. Linux – Haruskah Saya Menginstal 32 Atau 64 Bit?

  1. Linux – Kernel:Dukungan Namespaces?

  2. Linux – Kernel Tercemar Di Linux?

  3. Linux – Apakah Kernel Linux/unix yang Berbeda Dapat Dipertukarkan?