GNU/Linux >> Belajar Linux >  >> Linux

Bagaimana cara menyimpan kode yang dapat dieksekusi dalam memori bahkan di bawah tekanan memori? di Linux

PERINGATAN: Jangan gunakan tambalan ini jika Anda mengaktifkan swap, karena dua pengguna melaporkan efek yang lebih buruk. Saya hanya menguji tambalan ini dengan swap dinonaktifkan di kernel! (mis. CONFIG_SWAP tidak disetel)

Sampai pemberitahuan lebih lanjut (atau seseorang datang dengan sesuatu yang lebih baik), saya menggunakan (dan itu berfungsi, untuk saya) tambalan berikut untuk menghindari disk meronta-ronta / pembekuan OS ketika akan kehabisan Memori dan dengan demikian OOM-killer memicu sesegera mungkin (maks 1 detik):

revision 3
preliminary patch to avoid disk thrashing (constant reading) under memory pressure before OOM-killer triggers
more info: https://gist.github.com/constantoverride/84eba764f487049ed642eb2111a20830

diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 32699b2..7636498 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -208,7 +208,7 @@ enum lru_list {

 #define for_each_lru(lru) for (lru = 0; lru < NR_LRU_LISTS; lru++)

-#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_ACTIVE_FILE; lru++)
+#define for_each_evictable_lru(lru) for (lru = 0; lru <= LRU_INACTIVE_FILE; lru++)

 static inline int is_file_lru(enum lru_list lru)
 {
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 03822f8..1f3ffb5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2086,9 +2086,9 @@ static unsigned long shrink_list(enum lr
                 struct scan_control *sc)
 {
    if (is_active_lru(lru)) {
-       if (inactive_list_is_low(lruvec, is_file_lru(lru),
-                    memcg, sc, true))
-           shrink_active_list(nr_to_scan, lruvec, sc, lru);
+       //if (inactive_list_is_low(lruvec, is_file_lru(lru),
+       //           memcg, sc, true))
+       //  shrink_active_list(nr_to_scan, lruvec, sc, lru);
        return 0;
    }

@@ -2234,7 +2234,7 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,

    anon  = lruvec_lru_size(lruvec, LRU_ACTIVE_ANON, MAX_NR_ZONES) +
        lruvec_lru_size(lruvec, LRU_INACTIVE_ANON, MAX_NR_ZONES);
-   file  = lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
+   file  = //lruvec_lru_size(lruvec, LRU_ACTIVE_FILE, MAX_NR_ZONES) +
        lruvec_lru_size(lruvec, LRU_INACTIVE_FILE, MAX_NR_ZONES);

    spin_lock_irq(&pgdat->lru_lock);
@@ -2345,7 +2345,7 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
             sc->priority == DEF_PRIORITY);

    blk_start_plug(&plug);
-   while (nr[LRU_INACTIVE_ANON] || nr[LRU_ACTIVE_FILE] ||
+   while (nr[LRU_INACTIVE_ANON] || //nr[LRU_ACTIVE_FILE] ||
                    nr[LRU_INACTIVE_FILE]) {
        unsigned long nr_anon, nr_file, percentage;
        unsigned long nr_scanned;
@@ -2372,7 +2372,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
         * stop reclaiming one LRU and reduce the amount scanning
         * proportional to the original scan target.
         */
-       nr_file = nr[LRU_INACTIVE_FILE] + nr[LRU_ACTIVE_FILE];
+       nr_file = nr[LRU_INACTIVE_FILE] //+ nr[LRU_ACTIVE_FILE]
+           ;
        nr_anon = nr[LRU_INACTIVE_ANON] + nr[LRU_ACTIVE_ANON];

        /*
@@ -2391,7 +2392,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
            percentage = nr_anon * 100 / scan_target;
        } else {
            unsigned long scan_target = targets[LRU_INACTIVE_FILE] +
-                       targets[LRU_ACTIVE_FILE] + 1;
+                       //targets[LRU_ACTIVE_FILE] + 
+                       1;
            lru = LRU_FILE;
            percentage = nr_file * 100 / scan_target;
        }
@@ -2409,10 +2411,12 @@ static void shrink_node_memcg(struct pgl
        nr[lru] = targets[lru] * (100 - percentage) / 100;
        nr[lru] -= min(nr[lru], nr_scanned);

+       if (LRU_FILE != lru) { //avoid this block for LRU_ACTIVE_FILE
        lru += LRU_ACTIVE;
        nr_scanned = targets[lru] - nr[lru];
        nr[lru] = targets[lru] * (100 - percentage) / 100;
        nr[lru] -= min(nr[lru], nr_scanned);
+       }

        scan_adjusted = true;
    }

Sayangnya tab di atas diubah menjadi spasi, jadi jika Anda ingin tambalan mentah ada di sini.

Apa yang dilakukan tambalan ini bukanlah mengusir Active(file) halaman saat di bawah tekanan memori dan dengan demikian tidak menyebabkan kswapd0 (tetapi terlihat di iotop karena setiap program itu sendiri) untuk membaca kembali halaman yang dapat dieksekusi setiap proses yang berjalan setiap kali ada sakelar konteks untuk memungkinkan program untuk (terus) berjalan. Dengan demikian, banyak kerusakan disk dapat dihindari dan OS tidak macet.

Di atas diuji dengan kernel 4.18.5 (dan sekarang menguji 4.18.7) di dalam Qubes OS 4.0 dom0(Fedora 25) dan semua VM (Fedora 28) yang saya gunakan.

Untuk versi pertama tambalan ini, yang juga berfungsi dengan baik (tampaknya), lihat EDIT pada pertanyaan bahwa ini adalah jawaban dari.

PEMBARUAN: Setelah menggunakan tambalan ini untuk sementara waktu pada laptop ArchLinux dengan RAM 16G (minus 512M dicadangkan untuk kartu grafis terintegrasi) dan tanpa swap (dinonaktifkan di kernel juga) saya dapat mengatakan bahwa sistem dapat kehabisan memori lebih cepat daripada tanpa le9d.patch (rev. 3), dan pemicu OOM-killer untuk Xorg atau chromium atau lainnya ketika itu tidak akan terjadi tanpa tambalan. Dan sebagai mitigasi, yang sepertinya berhasil untuk saya sejauh ini, saya telah menjalankan echo 1 > /proc/sys/vm/drop_caches setiap kali Active(file) nomor di /proc/meminfo lebih dari 2G alias 2000000 KB (mis. dapatkan nomor KB melalui kode ini:grep 'Active(file):' /proc/meminfo|tr -d ' '|cut -f2 -d:|sed 's/kB//' ) dan melakukan pemeriksaan ini dengan sleep 5 setelah itu. Namun belakangan ini untuk mengkompilasi firefox-hg di /tmp yang merupakan tmpfs dan yang pada akhirnya menggunakan 12G dan memastikannya tidak terbunuh oleh OOM, saya telah menggunakan 500000 alih-alih 2000000 KB. Itu pasti lebih baik daripada membekukan seluruh sistem (mis. ketika tanpa le9d.patch) yang akan terjadi dalam kasus kompilasi firefox ini. Tanpa pemeriksaan ini, Active(file) tidak lebih tinggi dari 4G, tapi itu cukup untuk OOM-kill Xorg jika sesuatu menginginkan lebih banyak memori, seperti dalam kasus kompilasi firefox ini atau bahkan ketika hanya menyalin banyak gigabyte melalui komandan tengah malam (jika saya mengingatnya dengan benar).


Parameter memory.min di pengontrol memori cgroups-v2 akan membantu.

Yakni, izinkan saya mengutip:

"Perlindungan memori keras. Jika penggunaan memori cgroup berada dalam batas minimum efektifnya, memori cgroup tidak akan diklaim kembali dalam kondisi apa pun. Jika tidak ada memori yang dapat diklaim ulang tanpa perlindungan yang tersedia, OOM killer akan dipanggil."

https://www.kernel.org/doc/html/latest/admin-guide/cgroup-v2.html


Untuk menjawab pertanyaan, inilah tambalan sederhana/pendahuluan untuk tidak mengusir Active(file) (seperti yang terlihat di /proc/meminfo ) jika kurang dari 256 MiB, tampaknya berfungsi dengan baik (tanpa disk thrashing) dengan linux-stable 5.2.4:

diff --git a/mm/vmscan.c b/mm/vmscan.c
index dbdc46a84f63..7a0b7e32ff45 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2445,6 +2445,13 @@ static void get_scan_count(struct lruvec *lruvec, struct mem_cgroup *memcg,
            BUG();
        }

+    if (NR_ACTIVE_FILE == lru) {
+      long long kib_active_file_now=global_node_page_state(NR_ACTIVE_FILE) * MAX_NR_ZONES;
+      if (kib_active_file_now <= 256*1024) {
+        nr[lru] = 0; //don't reclaim any Active(file) (see /proc/meminfo) if they are under 256MiB
+        continue;
+      }
+    }
        *lru_pages += size;
        nr[lru] = scan;
    }

Perhatikan bahwa beberapa belum ditemukan regresi pada kernel 5.3.0-rc4-gd45331b00ddb akan menyebabkan pembekuan sistem (tanpa disk thrashing, dan sysrq akan tetap berfungsi) bahkan tanpa tambalan ini.

(setiap perkembangan baru yang terkait dengan ini harus terjadi di sini.)


Linux
  1. Linux – Bagaimana Menguji Apakah Biner Linux Dikompilasi Sebagai Kode Independen Posisi?

  2. Cara menggunakan FTP di Linux untuk mentransfer file

  3. Cara menggunakan perintah tar di Linux

  1. Cara menggunakan pengalihan perintah di Linux

  2. Bagaimana cara membuat kode modul kernel Linux?

  3. Bagaimana cara menilai batas pipa di bawah linux?

  1. Bagaimana cara membongkar, memodifikasi, dan kemudian memasang kembali executable Linux?

  2. Bagaimana cara membongkar biner yang dapat dieksekusi di Linux untuk mendapatkan kode perakitan?

  3. Cara mengetahui penggunaan memori pengguna di linux