Rumah  >  Artikel  >  Tutorial sistem  >  Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori

Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori

王林
王林ke hadapan
2024-02-13 15:15:13656semak imbas

Pernahkah anda menghadapi pelbagai masalah ingatan dalam sistem Linux? Seperti kebocoran memori, pemecahan memori, dll. Masalah ini boleh diselesaikan melalui pemahaman mendalam tentang model memori Linux.

1 Inti Linux menyokong tiga model ingatan, iaitu model ingatan rata, model ingatan tak bersambung dan model ingatan jarang. Model memori yang dipanggil sebenarnya merujuk kepada pengagihan memori fizikal dari perspektif CPU dan kaedah yang digunakan untuk menguruskan ingatan fizikal ini dalam kernel Linux. Di samping itu, perlu diingatkan bahawa artikel ini tertumpu terutamanya pada sistem memori yang dikongsi, yang bermaksud bahawa semua CPU berkongsi ruang alamat fizikal.

Kandungan artikel ini disusun seperti berikut: Untuk menganalisis model memori dengan jelas, kami menerangkan beberapa istilah asas, iaitu dalam Bab 2. Bab ketiga menerangkan prinsip kerja tiga model memori Bab terakhir ialah analisis kod Kod ini berasal dari kernel 4.4.6 Untuk kod berkaitan seni bina, kami menggunakan ARM64 untuk analisis.

2. Istilah berkaitan model memori

1. Apakah bingkai halaman?

Salah satu fungsi sistem pengendalian yang paling penting ialah mengurus pelbagai sumber dalam sistem komputer Sebagai sumber yang paling penting: ingatan, kita mesti menguruskannya. Dalam sistem pengendalian Linux, memori fizikal diuruskan mengikut saiz halaman Saiz halaman tertentu berkaitan dengan perkakasan dan konfigurasi sistem Linux adalah tetapan paling klasik. Oleh itu, untuk ingatan fizikal, kami membahagikannya kepada halaman yang disusun mengikut saiz halaman Kawasan memori saiz halaman dalam setiap memori fizikal dipanggil bingkai halaman. Kami mewujudkan struktur data halaman struktur untuk setiap bingkai halaman fizikal untuk menjejaki penggunaan setiap halaman fizikal: Adakah ia digunakan untuk segmen teks kernel? Atau adakah ia jadual halaman untuk proses? Adakah ia digunakan untuk pelbagai cache fail atau dalam keadaan bebas...

Setiap bingkai halaman mempunyai struktur data halaman yang sepadan. tiga model memori dalam kernel Linux diterangkan secara terperinci.

2. Apakah itu PFN?

Untuk sistem komputer, keseluruhan ruang alamat fizikalnya hendaklah ruang alamat bermula dari 0 dan berakhir dengan ruang fizikal maksimum yang boleh disokong oleh sistem sebenar. Dalam sistem ARM, dengan mengandaikan alamat fizikal ialah 32 bit, maka ruang alamat fizikal ialah 4G Dalam sistem ARM64, jika bilangan bit alamat fizikal yang disokong ialah 48, maka ruang alamat fizikal ialah 256T. Sudah tentu, sebenarnya, tidak semua ruang alamat fizikal yang besar digunakan untuk ingatan, ada juga yang tergolong dalam ruang I/O (sudah tentu, sesetengah gerbang CPU mempunyai ruang alamat io bebas mereka sendiri). Oleh itu, ruang alamat fizikal yang diduduki oleh memori haruslah selang terhad, dan adalah mustahil untuk menampung keseluruhan ruang alamat fizikal. Namun, kini memori semakin besar dan besar, untuk sistem 32-bit, ruang alamat fizikal 4G tidak lagi dapat memenuhi keperluan memori, jadi terdapat konsep ingatan tinggi, yang akan diterangkan secara terperinci kemudian.

PFN ialah singkatan nombor bingkai halaman Yang dipanggil bingkai halaman merujuk kepada ingatan fizikal Memori fizikal dibahagikan kepada kawasan saiz halaman dan setiap halaman adalah nombor PFN. Dengan mengandaikan bahawa ingatan fizikal bermula pada alamat 0, maka bingkai halaman dengan PFN sama dengan 0 ialah halaman yang bermula pada alamat 0 (alamat fizikal). Dengan mengandaikan bahawa memori fizikal bermula pada alamat x, maka nombor bingkai halaman pertama ialah (x>>PAGE_SHIFT).

3 Apakah itu NUMA?

Terdapat dua pilihan semasa mereka bentuk seni bina memori untuk sistem berbilang pemproses: Satu ialah UMA (Semua pemproses dalam sistem berkongsi ruang memori fizikal yang bersatu dan konsisten, tidak kira pemproses mana yang memulakan akses ke alamat memori). adalah sama. NUMA (Akses memori tidak seragam) adalah berbeza daripada UMA Akses ke alamat memori tertentu berkaitan dengan kedudukan relatif antara memori dan pemproses. Contohnya, untuk pemproses pada nod, mengakses memori tempatan mengambil masa lebih lama daripada mengakses memori jauh.

3. Tiga model memori dalam kernel Linux

1. Apakah model memori FLAT?

Jika dari perspektif mana-mana pemproses dalam sistem, apabila ia mengakses memori fizikal, ruang alamat fizikal adalah ruang alamat berterusan tanpa lubang, maka model memori sistem komputer ini adalah Memori Flat. Di bawah model ingatan ini, pengurusan memori fizikal adalah agak mudah Setiap bingkai halaman fizikal akan mempunyai struktur data halaman untuk mengabstrakkannya. Oleh itu, terdapat tatasusunan halaman struct (mem_map) dalam sistem, dan setiap entri tatasusunan halaman fizikal sebenar (bingkai halaman). Dalam kes ingatan rata, hubungan antara PFN (nombor bingkai halaman) dan indeks tatasusunan mem_map adalah linear (terdapat offset tetap, jika alamat fizikal yang sepadan dengan memori adalah sama dengan 0, maka PFN ialah indeks tatasusunan). Oleh itu, adalah sangat mudah untuk pergi dari PFN ke struktur data halaman yang sepadan, dan sebaliknya untuk butiran, sila rujuk takrifan page_to_pfn dan pfn_to_page. Di samping itu, untuk model ingatan rata, hanya terdapat satu nod (struct pglist_data) (untuk menggunakan mekanisme yang sama seperti Model Memori Discontiguous). Gambar di bawah menerangkan keadaan ingatan yang rata:

Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori

Perlu ditekankan bahawa memori yang diduduki oleh halaman struct berada dalam julat yang dipetakan secara langsung, jadi sistem pengendalian tidak perlu mencipta jadual halaman untuknya.

2. Apakah Model Memori Berpisah?

Sekiranya ruang alamat CPU mempunyai beberapa lubang dan tidak berterusan semasa mengakses memori fizikal, maka model memori sistem komputer ini ialah Memori Discontiguous. Secara umumnya, model memori sistem komputer berasaskan NUMA ialah Memori Discontiguous Namun, kedua-dua konsep itu sebenarnya berbeza. NUMA menekankan hubungan kedudukan antara memori dan pemproses, yang tiada kaitan dengan model memori Walau bagaimanapun, kerana memori dan pemproses pada nod yang sama mempunyai hubungan gandingan yang lebih rapat (akses lebih pantas), berbilang nod diperlukan untuk mengurusnya. Memori bersebelahan pada asasnya adalah lanjutan daripada model memori memori rata Kebanyakan ruang alamat keseluruhan memori fizikal adalah sekeping memori yang besar, dengan beberapa lubang di tengah Setiap bahagian ruang alamat memori adalah milik nod terhad kepada satu Secara dalaman, model memori nod ialah memori rata). Gambar di bawah menerangkan situasi ingatan Berpisah:

Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori

Oleh itu, di bawah model memori ini, terdapat berbilang data nod (struct pglist_data), dan definisi makro NODE_DATA boleh mendapatkan struct pglist_data nod yang ditentukan. Walau bagaimanapun, memori fizikal yang diuruskan oleh setiap nod disimpan dalam ahli node_mem_map struktur data pglist_data struct (konsepnya serupa dengan mem_map dalam memori rata). Pada masa ini, menukar daripada PFN kepada halaman struktur tertentu akan menjadi lebih rumit sedikit Pertama kita perlu mendapatkan ID nod daripada PFN, dan kemudian mencari struktur data pglist_data yang sepadan berdasarkan ID ini, dan kemudian cari tatasusunan halaman yang sepadan. Kaedah seterusnya ialah ingatan rata yang serupa.

3. Apakah Model Memori Jarang?

Model memori juga merupakan proses evolusi Pada mulanya, memori rata telah digunakan untuk mengabstrakkan ruang alamat memori berterusan (mem_maps[]). Ia ialah ruang alamat memori yang berterusan, iaitu, mem_maps tunggal asal[] telah menjadi beberapa peta_mem[]. Semuanya kelihatan sempurna, tetapi kemunculan palam panas memori menjadikan reka bentuk sempurna asal tidak sempurna, kerana walaupun mem_maps[] dalam nod mungkin tidak berterusan. Malah, selepas kemunculan ingatan jarang, model memori ingatan Discontiguous tidak lagi penting. Ini bermakna bahawa memori jarang akhirnya boleh menggantikan memori Discontiguous ini sedang dijalankan pilih daripada.

Mengapa dikatakan bahawa ingatan yang jarang akhirnya boleh menggantikan ingatan yang tidak bersebelahan? Malah, di bawah model memori jarang, ruang alamat berterusan dibahagikan kepada bahagian mengikut BAHAGIAN (contohnya, 1G), dan setiap bahagian disambungkan ke palam panas Oleh itu, di bawah memori jarang, ruang alamat memori boleh dibahagikan kepada lebih banyak bahagian terperinci , menyokong memori Discontiguous yang lebih diskret. Di samping itu, sebelum ingatan jarang muncul, ingatan NUMA dan Discontiguous sentiasa berada dalam hubungan yang mengelirukan: NUMA tidak menetapkan kesinambungan ingatannya, dan sistem memori Discontiguous tidak semestinya sistem NUMA, tetapi kedua-dua konfigurasi ini Semuanya berbilang- nod. Dengan ingatan yang jarang, kita akhirnya boleh memisahkan konsep kesinambungan ingatan daripada NUMA: sistem NUMA boleh menjadi memori rata atau memori jarang, dan sistem ingatan jarang boleh menjadi NUMA atau UMA .

Gambar di bawah menggambarkan bagaimana memori yang jarang menguruskan bingkai halaman (SPARSEMEM_EXTREME dikonfigurasikan):

Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori

(Nota: Penunjuk bahagian_mem dalam gambar di atas harus menghala ke halaman, dan terdapat beberapa unit data bahagian_mem struct dalam halaman)

Seluruh ruang alamat fizikal yang berterusan dipotong bahagian demi bahagian Di dalam setiap bahagian, ingatannya adalah berterusan (iaitu, ia mematuhi ciri-ciri memori rata, susunan halaman mem_map dilampirkan pada struktur bahagian (). struct mem_section) Daripada struktur nod (struct pglist_data). Sudah tentu, tidak kira model memori yang digunakan, surat-menyurat antara PFN dan halaman perlu diproses Walau bagaimanapun, memori jarang mempunyai konsep tambahan bahagian, menjadikan penukaran kepada PFNSectionpage.

Mari kita lihat dahulu cara menukar daripada PFN kepada struktur halaman: tatasusunan penuding bahagian mem_ditakrifkan secara statik dalam kernel Bahagian A selalunya merangkumi berbilang halaman, jadi adalah perlu untuk menukar PFN kepada nombor bahagian dengan beralih ke kanan, menggunakan nombor bahagian. Untuk indeks, struktur data bahagian yang sepadan dengan PFN boleh didapati dalam tatasusunan penunjuk bahagian mem_. Selepas mencari bahagian, anda boleh menemui struktur data halaman yang sepadan di sepanjang peta_mem_bahagiannya. Ngomong-ngomong, pada mulanya, memori jarang menggunakan tatasusunan memory_section satu dimensi (bukan tatasusunan penuding) Pelaksanaan ini sangat membazirkan memori untuk sistem yang jarang (CONFIG_SPARSEMEM_EXTREME). Di samping itu, adalah lebih mudah untuk menyimpan penunjuk untuk sokongan palam panas Jika penunjuk adalah sama dengan NULL, ia bermakna bahagian itu tidak wujud. Gambar di atas menerangkan situasi tatasusunan penunjuk mem_section satu dimensi (SPARSEMEM_EXTREME dikonfigurasikan untuk konfigurasi bukan SPARSEMEM_EXTREME, konsepnya adalah serupa. Anda boleh membaca kod itu sendiri untuk operasi tertentu.

Sedikit menyusahkan untuk pergi dari halaman ke PFN Sebenarnya, PFN terbahagi kepada dua bahagian: satu bahagian adalah indeks bahagian, dan bahagian lain adalah offset halaman dalam bahagian. Mula-mula kita perlu mendapatkan indeks bahagian dari halaman, dan kemudian mendapatkan bahagian memori yang sepadan. Mengetahui bahagian memori bermakna halaman itu berada dalam peta bahagian_mem, dan kami juga tahu mengimbangi halaman tersebut Akhirnya, kami boleh mensintesis PFN . Untuk penukaran halaman kepada indeks bahagian, memori jarang mempunyai dua penyelesaian Mari kita lihat penyelesaian klasik dahulu, yang disimpan dalam page->flags (SECTION_IN_PAGE_FLAGS dikonfigurasikan). Masalah terbesar dengan kaedah ini ialah bilangan bit dalam page->flags tidak semestinya mencukupi, kerana bendera ini membawa terlalu banyak maklumat Pelbagai bendera halaman, id nod dan id zon kini menambah id bahagian yang tidak dapat dicapai konsistensi dalam seni bina yang berbeza Adakah terdapat algoritma universal? Ini ialah CONFIG_SPARSEMEM_VMEMMAP. Untuk algoritma khusus, sila rujuk rajah di bawah:

Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori

(Ada masalah dengan gambar di atas. vmemmap hanya menunjuk ke tatasusunan halaman struct pertama apabila PHYS_OFFSET bersamaan dengan 0. Secara umumnya, harus ada offset, tetapi saya terlalu malas untuk mengubahnya, haha)

Untuk model memori jarang klasik, memori yang diduduki oleh tatasusunan halaman struktur bahagian datang daripada kawasan yang dipetakan secara langsung Jadual halaman ditetapkan semasa permulaan, dan bingkai halaman diperuntukkan, yang bermaksud bahawa alamat maya diperuntukkan. Walau bagaimanapun, untuk SPARSEMEM_VMEMMAP, alamat maya diperuntukkan dari awal Ia adalah ruang alamat maya berterusan bermula dari vmemmap Setiap halaman mempunyai halaman struktur yang sepadan, hanya ada alamat maya. Oleh itu, apabila bahagian ditemui, alamat maya halaman struct yang sepadan sudah tentu, ia juga perlu untuk memperuntukkan bingkai halaman fizikal dan kemudian mewujudkan jadual halaman, untuk jenis memori yang jarang. overhed akan menjadi lebih besar sedikit (satu lagi proses mewujudkan pemetaan).

4. Analisis kod

Analisis kod kami dijalankan terutamanya melalui include/asm-generic/memory_model.h.

1. Ingatan rata. Kodnya adalah seperti berikut:

\#define __pfn_to_page(pfn)  (mem_map + ((pfn) - ARCH_PFN_OFFSET)) 
\#define __page_to_pfn(page)  ((unsigned long)((page) - mem_map) + ARCH_PFN_OFFSET)

Ia boleh dilihat daripada kod bahawa PFN dan indeks tatasusunan halaman (mem_map) adalah berkaitan secara linear, dan terdapat offset tetap yang dipanggil ARCH_PFN_OFFSET mengimbangi ini berkaitan dengan seni bina yang dianggarkan. Untuk ARM64, ia ditakrifkan dalam fail arch/arm/include/asm/memory.h Sudah tentu, definisi ini berkaitan dengan ruang alamat fizikal yang diduduki oleh memori (iaitu, berkaitan dengan definisi PHYS_OFFSET).

2. Model Ingatan Tak Sebelah. Kodnya adalah seperti berikut:

\#define __pfn_to_page(pfn)      \ 
({  unsigned long __pfn = (pfn);    \ 
unsigned long __nid = arch_pfn_to_nid(__pfn); \ 
NODE_DATA(__nid)->node_mem_map + arch_local_page_offset(__pfn, __nid);\ 
})

\#define __page_to_pfn(pg)            \ 
({  const struct page *__pg = (pg);          \ 
struct pglist_data *__pgdat = NODE_DATA(page_to_nid(__pg));  \ 
(unsigned long)(__pg - __pgdat->node_mem_map) +      \ 
__pgdat->node_start_pfn;          \ 
})

Discontiguous Memory Model需要获取node id,只要找到node id,一切都好办了,比对flat memory model进行就OK了。因此对于__pfn_to_page的定义,可以首先通过arch_pfn_to_nid将PFN转换成node id,通过NODE_DATA宏定义可以找到该node对应的pglist_data数据结构,该数据结构的node_start_pfn记录了该node的第一个page frame number,因此,也就可以得到其对应struct page在node_mem_map的偏移。__page_to_pfn类似,大家可以自己分析。

3、Sparse Memory Model。经典算法的代码我们就不看了,一起看看配置了SPARSEMEM_VMEMMAP的代码,如下:

\#define __pfn_to_page(pfn)  (vmemmap + (pfn)) 
\#define __page_to_pfn(page)  (unsigned long)((page) - vmemmap)

简单而清晰,PFN就是vmemmap这个struct page数组的index啊。对于ARM64而言,vmemmap定义如下:

\#define vmemmap      ((struct page *)VMEMMAP_START - \ 
      SECTION_ALIGN_DOWN(memstart_addr >> PAGE_SHIFT))

毫无疑问,我们需要在虚拟地址空间中分配一段地址来安放struct page数组(该数组包含了所有物理内存跨度空间page),也就是VMEMMAP_START的定义。

总之,Linux内存模型是一个非常重要的概念,可以帮助你更好地理解Linux系统中的内存管理。如果你想了解更多关于这个概念的信息,可以查看本文提供的参考资料。

Atas ialah kandungan terperinci Model Memori Linux: Pemahaman Lebih Mendalam Mengenai Pengurusan Memori. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:lxlinux.net. Jika ada pelanggaran, sila hubungi admin@php.cn Padam