วิธีใช้คำสั่ง pmap บน Linux
เผยแพร่แล้ว: 2022-06-25 การค้นหาว่ากระบวนการ Linux ใช้ RAM มากเพียงใดนั้นไม่ใช่เรื่องง่าย โดยเฉพาะอย่างยิ่งเมื่อจำเป็นต้องพิจารณาหน่วยความจำที่ใช้ร่วมกัน โชคดีที่คำสั่ง pmap
ช่วยให้คุณเข้าใจทุกอย่างได้
การทำแผนที่หน่วยความจำ
บนระบบปฏิบัติการสมัยใหม่ แต่ละกระบวนการอาศัยอยู่ในพื้นที่หน่วยความจำหรือ พื้นที่จัดสรรที่จัดสรร ไว้ ขอบเขตของภูมิภาคที่จัดสรรจะไม่ถูกแมปโดยตรงกับที่อยู่ฮาร์ดแวร์จริง ระบบปฏิบัติการสร้างพื้นที่หน่วยความจำเสมือนสำหรับแต่ละกระบวนการและทำหน้าที่เป็นชั้นนามธรรมที่แมปหน่วยความจำเสมือนกับหน่วยความจำกายภาพ
เคอร์เนลรักษาตารางการแปลสำหรับแต่ละกระบวนการ และเข้าถึงได้โดย CPU เมื่อเคอร์เนลเปลี่ยนกระบวนการที่ทำงานบนคอร์ CPU เฉพาะ เคอร์เนลจะอัพเดตตารางการแปลที่เชื่อมโยงกระบวนการและคอร์ของ CPU เข้าด้วยกัน
ประโยชน์ของนามธรรม
มีประโยชน์กับโครงการนี้ การใช้หน่วยความจำค่อนข้างถูกห่อหุ้มและแซนด์บ็อกซ์สำหรับแต่ละกระบวนการใน userland กระบวนการเพียง "เห็น" หน่วยความจำในแง่ของที่อยู่หน่วยความจำเสมือน ซึ่งหมายความว่าสามารถทำงานได้เฉพาะกับหน่วยความจำที่ได้รับจากระบบปฏิบัติการเท่านั้น เว้นแต่จะมีสิทธิ์เข้าถึงหน่วยความจำที่ใช้ร่วมกันบางรายการก็ไม่ทราบหรือเข้าถึงหน่วยความจำที่จัดสรรให้กับกระบวนการอื่นไม่ได้
การแยกหน่วยความจำกายภาพที่ใช้ฮาร์ดแวร์เป็นที่อยู่หน่วยความจำเสมือนช่วยให้เคอร์เนลเปลี่ยนที่อยู่ทางกายภาพที่หน่วยความจำเสมือนบางส่วนถูกแมปไป สามารถสลับหน่วยความจำไปยังดิสก์โดยเปลี่ยนที่อยู่จริงที่ภูมิภาคของหน่วยความจำเสมือนชี้ไป นอกจากนี้ยังสามารถชะลอการให้หน่วยความจำกายภาพได้จนกว่าจะมีความต้องการจริง
ตราบใดที่คำขออ่านหรือเขียนหน่วยความจำได้รับบริการตามที่ร้องขอ เคอร์เนลสามารถเล่นปาหี่ตารางการแมปได้อย่างอิสระตามที่เห็นสมควร
RAM ตามความต้องการ
ตารางการทำแผนที่และแนวคิดของ “RAM ตามความต้องการ” เปิดโอกาสให้ มีหน่วยความจำที่ใช้ร่วมกัน ได้ เคอร์เนลจะพยายามหลีกเลี่ยงการโหลดสิ่งเดียวกันลงในหน่วยความจำมากกว่าหนึ่งครั้ง ตัวอย่างเช่น มันจะโหลดไลบรารีที่ใช้ร่วมกันลงในหน่วยความจำหนึ่งครั้ง และแมปกับกระบวนการต่าง ๆ ที่จำเป็นต้องใช้ แต่ละกระบวนการจะมีที่อยู่เฉพาะของตัวเองสำหรับไลบรารีที่ใช้ร่วมกัน แต่ทั้งหมดจะชี้ไปที่ตำแหน่งจริงเดียวกัน
ถ้าพื้นที่ที่ใช้ร่วมกันของหน่วยความจำสามารถเขียนได้ เคอร์เนลจะใช้รูปแบบที่เรียกว่า copy-on-write หากกระบวนการหนึ่งเขียนไปยังหน่วยความจำที่แบ่งใช้ และกระบวนการอื่นที่แชร์หน่วยความจำนั้นไม่ควรเห็นการเปลี่ยนแปลง สำเนาของหน่วยความจำที่แบ่งใช้จะถูกสร้างขึ้นที่จุดของคำขอเขียน
เคอร์เนลลินุกซ์ 2.6.32 ซึ่งเผยแพร่ในเดือนธันวาคม 2552 ทำให้ลินุกซ์มีคุณลักษณะที่เรียกว่า “การรวมเคอร์เนล SamePage” ซึ่งหมายความว่า Linux สามารถตรวจจับพื้นที่ที่เหมือนกันของข้อมูลในพื้นที่ที่อยู่ที่แตกต่างกัน ลองนึกภาพชุดของเครื่องเสมือนที่ทำงานบนคอมพิวเตอร์เครื่องเดียว และเครื่องเสมือนทั้งหมดใช้ระบบปฏิบัติการเดียวกัน การใช้แบบจำลองหน่วยความจำที่ใช้ร่วมกันและการคัดลอกเมื่อเขียน ค่าใช้จ่ายในคอมพิวเตอร์โฮสต์จะลดลงอย่างมาก
ทั้งหมดนี้ทำให้การจัดการหน่วยความจำใน Linux มีความซับซ้อนและเหมาะสมที่สุดเท่าที่จะทำได้ แต่ความซับซ้อนนั้นทำให้ยากต่อการดูกระบวนการและรู้ว่าการใช้หน่วยความจำจริงๆ คืออะไร
ยูทิลิตี้ pmap
เคอร์เนลเปิดเผยข้อมูลหลายอย่างที่มันทำกับ RAM ผ่านไฟล์หลอกสองไฟล์ในระบบไฟล์หลอกข้อมูลระบบ “/proc” มีสองไฟล์ต่อกระบวนการ ซึ่งตั้งชื่อตาม ID กระบวนการหรือ PID ของแต่ละกระบวนการ: “/proc/maps” และ “/proc//smaps”
เครื่องมือ pmap
อ่านข้อมูลจากไฟล์เหล่านี้และแสดงผลลัพธ์ในหน้าต่างเทอร์มินัล จะเห็นได้ชัดว่าเราจำเป็นต้องระบุ PID ของกระบวนการที่เราสนใจทุกครั้งที่เราใช้ pmap
ค้นหา ID กระบวนการ
มีหลายวิธีในการค้นหา PID ของกระบวนการ นี่คือซอร์สโค้ดสำหรับโปรแกรมเล็กน้อยที่เราจะใช้ในตัวอย่างของเรา มันเขียนด้วยภาษา C ทั้งหมดที่ทำคือพิมพ์ข้อความไปที่หน้าต่างเทอร์มินัลและรอให้ผู้ใช้กดปุ่ม "Enter"
#include <stdio.h> int main(int argc, ถ่าน *argv[]) { printf("โปรแกรมทดสอบ How-To Geek"); getc(stdin); } // จบ main
โปรแกรมถูกคอมไพล์ไปยังไฟล์เรียกทำงาน pm
โดยใช้คอมไพเลอร์ gcc
:
gcc -o pm pm.c
เนื่องจากโปรแกรมจะรอให้ผู้ใช้กด Enter โปรแกรมจะทำงานต่อไปตราบเท่าที่เราต้องการ
./pm
โปรแกรมจะเปิดขึ้น พิมพ์ข้อความ และรอการกดแป้นพิมพ์ ตอนนี้เราสามารถค้นหา PID ของมันได้แล้ว คำสั่ง ps
แสดงรายการกระบวนการที่ทำงานอยู่ ตัวเลือก -e
(แสดงกระบวนการทั้งหมด) ทำให้ ps
แสดงรายการทุกกระบวนการ เราจะไพพ์เอาต์พุตผ่าน grep
และกรองรายการที่มี “pm” อยู่ในชื่อ
ps -e | grep pm
รายการนี้จะแสดงรายการทั้งหมดที่มี “pm” ที่ใดก็ได้ในชื่อ
เราสามารถเจาะจงมากขึ้นโดยใช้คำสั่ง pidof
เราให้ชื่อของกระบวนการที่เราสนใจในบรรทัดคำสั่ง pidof
และพยายามค้นหารายการที่ตรงกัน หากพบการจับคู่ pidof
จะพิมพ์ PID ของกระบวนการจับคู่
pidof pm
วิธี pidof
จะเรียบร้อยกว่าเมื่อคุณรู้ชื่อของกระบวนการ แต่วิธี ps
จะทำงานแม้ว่าจะรู้เพียงบางส่วนของชื่อกระบวนการก็ตาม
ใช้ pmap
เมื่อโปรแกรมทดสอบของเราทำงาน และเมื่อเราระบุ PID แล้ว เราก็สามารถใช้ pmap ได้ดังนี้:
pmap 40919
การแมปหน่วยความจำสำหรับกระบวนการแสดงไว้สำหรับเรา
นี่คือผลลัพธ์ทั้งหมดจากคำสั่ง:
40919: ./pm 000056059f06c000 4K r ---- pm 000056059f06d000 4K rx-- pm 000056059f06e000 4K r ---- pm 000056059f06f000 4K r ---- pm 000056059f070000 4K rw--- pm 000056059fc39000 132K rw--- [ อานนท์ ] 00007f97a3edb000 8K rw--- [ อานนท์ ] 00007f97a3edd000 160K r---- libc.so.6 00007f97a3f05000 1616K rx-- libc.so.6 00007f97a4099000 352K r---- libc.so.6 00007f97a40f1000 4K ----- libc.so.6 00007f97a40f2000 16K r---- libc.so.6 00007f97a40f6000 8K rw--- libc.so.6 00007f97a40f8000 60K rw--- [ อานนท์ ] 00007f97a4116000 4K r---- ld-linux-x86-64.so.2 00007f97a4117000 160K rx-- ld-linux-x86-64.so.2 00007f97a413f000 40K r---- ld-linux-x86-64.so.2 00007f97a4149000 8K r---- ld-linux-x86-64.so.2 00007f97a414b000 8K rw--- ld-linux-x86-64.so.2 00007ffca0e7e000 132K rw--- [ กอง ] 0007ffca0fe1000 16K r---- [ อานนท์ ] 00007ffca0fe5000 8K rx-- [ อานนท์ ] ffffffffff6000000 4K --x-- [ นาน ] รวม 2756K
บรรทัดแรกคือชื่อกระบวนการและ PID บรรทัดอื่นแต่ละบรรทัดแสดงที่อยู่หน่วยความจำที่แมป และจำนวนหน่วยความจำที่ที่อยู่นั้น แสดงเป็นกิโลไบต์ อักขระห้าตัวถัดไปของแต่ละบรรทัดเรียกว่าการ อนุญาตหน่วยความจำเสมือน สิทธิ์ที่ถูกต้องคือ:
- r : หน่วยความจำที่แมปสามารถอ่านได้โดยกระบวนการ
- w : หน่วยความจำที่แมปสามารถเขียนได้โดยกระบวนการ
- x : กระบวนการสามารถดำเนินการคำสั่งใด ๆ ที่มีอยู่ในหน่วยความจำที่แมป
- s : หน่วยความจำที่แมปถูกแชร์ และการเปลี่ยนแปลงที่ทำกับหน่วยความจำที่แชร์นั้นสามารถมองเห็นได้ในทุกกระบวนการที่แชร์หน่วยความจำ
- R : ไม่มีการสำรองพื้นที่สว็อปสำหรับหน่วยความจำที่แมปนี้
ข้อมูลสุดท้ายในแต่ละบรรทัดคือชื่อของแหล่งที่มาของการทำแผนที่ ซึ่งอาจเป็นชื่อกระบวนการ ชื่อไลบรารี หรือชื่อระบบ เช่น สแต็กหรือฮีป
จอแสดงผลแบบขยาย
ตัวเลือก -x
(ขยาย) ให้คอลัมน์พิเศษสองคอลัมน์
pmap -x 40919
คอลัมน์จะได้รับชื่อ เราได้เห็นคอลัมน์ "Address", "Kbytes", "Mode" และ "Mapping" แล้ว คอลัมน์ใหม่นี้เรียกว่า "RSS" และ "Dirty"
นี่คือผลลัพธ์ที่สมบูรณ์:
40919: ./pm ที่อยู่ Kbytes RSS Dirty Mode Mapping 000056059f06c000 4 4 0 r ---- pm 000056059f06d000 4 4 0 rx-- pm 000056059f06e000 4 4 0 r ---- pm 000056059f06f000 4 4 4 r ---- pm 000056059f070000 4 4 4 rw--- pm 000056059fc39000 132 4 4 rw--- [ อานนท์ ] 00007f97a3edb000 8 4 4 rw--- [ อานนท์ ] 00007f97a3edd000 160 160 0 r ---- libc.so.6 00007f97a3f05000 1616 788 0 rx-- libc.so.6 00007f97a4099000 352 64 0 r ---- libc.so.6 00007f97a40f1000 4 0 0 ----- libc.so.6 00007f97a40f2000 16 16 16 r ---- libc.so.6 00007f97a40f6000 8 8 8 rw--- libc.so.6 00007f97a40f8000 60 28 28 rw--- [ อานนท์ ] 00007f97a4116000 4 4 0 r ---- ld-linux-x86-64.so.2 00007f97a4117000 160 160 0 rx-- ld-linux-x86-64.so.2 00007f97a413f000 40 40 0 r ---- ld-linux-x86-64.so.2 00007f97a4149000 8 8 8 r ---- ld-linux-x86-64.so.2 00007f97a414b000 8 8 8 rw--- ld-linux-x86-64.so.2 00007ffca0e7e000 132 12 12 rw--- [ กอง ] 00007ffca0fe1000 16 0 0 r---- [ อานนท์ ] 00007ffca0fe5000 8 4 0 rx-- [ อานนท์ ] ffffffffff600000 4 0 0 --x-- [ อานนท์ ] ------ ------- ------- ------- รวม kB 2756 1328 96
- RSS : นี่คือ ขนาดของชุดที่อยู่อาศัย นั่นคือจำนวนหน่วยความจำที่อยู่ใน RAM และไม่มีการสลับออก
- สกปรก : หน่วยความจำ "สกปรก" เปลี่ยนไปตั้งแต่เริ่มกระบวนการและการทำแผนที่
แสดงให้ฉันเห็นทุกอย่าง
-X
(มากกว่าแบบขยาย) เพิ่มคอลัมน์เพิ่มเติมให้กับผลลัพธ์ สังเกตตัวพิมพ์ใหญ่ "X" ตัวเลือกอื่นที่เรียกว่า -XX
(มากกว่า -X
) จะแสดงให้คุณเห็นทุกสิ่ง pmap
สามารถรับได้จากเคอร์เนล เนื่องจาก -X
เป็นสับเซตของ -XX
เราจะอธิบายผลลัพธ์จาก -XX
pmap -XX 40919
เอาต์พุตล้อมรอบอย่างน่ากลัวในหน้าต่างเทอร์มินัลและไม่สามารถอ่านได้จริง นี่คือผลลัพธ์แบบเต็ม:
40919: ./pm ที่อยู่ Perm Offset Device ขนาดไอโหนด KernelPageSize MMUPageSize Rss Pss Shared_Clean Shared_Dirty Private_Clean Private_Dirty อ้างอิง ไม่ระบุชื่อ LazyFree AnonHugePages ShmemPmdMapped FilePmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked THPelig 56059f06c000 r--p 00000000 08:03 393304 4 4 4 4 4 0 0 4 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 rd mr mw me dw sd pm 56059f06d000 r-xp 00001000 08:03 393304 4 4 4 4 4 0 0 4 0 4 0 0 0 0 0 0 0 0 0 0 0 0 rd อดีต คุณ mw ฉัน dw sd pm 56059f06e000 r--p 00002000 08:03 393304 4 4 4 4 4 0 0 4 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0 rd mr mw me dw sd pm 56059f06f000 r--p 00002000 08:03 393304 4 4 4 4 4 0 0 0 4 4 4 0 0 0 0 0 0 0 0 0 0 0 rd mr mw me dw ac sd pm 56059f070000 rw-p 00003000 08:03 393304 4 4 4 4 4 0 0 0 4 4 4 0 0 0 0 0 0 0 0 0 0 0 rd wr mr mw ฉัน dw ac sd pm 56059fc39000 rw-p 00000000 00:00 0 132 4 4 4 4 0 0 0 4 4 4 0 0 0 0 0 0 0 0 0 0 0 rd wr mr mw ฉัน ac sd [heap] 7f97a3edb000 rw-p 00000000 00:00 0 8 4 4 4 4 0 0 0 4 4 4 0 0 0 0 0 0 0 0 0 0 0 rd wr นาย mw ฉัน ac sd 7f97a3edd000 r--p 00000000 08:03 264328 160 4 4 160 4 160 0 0 160 0 0 0 0 0 0 0 0 0 0 0 0 rd mr mw ฉัน sd libc.so.6 7f97a3f05000 r-xp 00028000 08:03 264328 1616 4 4 788 32 788 0 0 0 788 0 0 0 0 0 0 0 0 0 0 0 rd อดีต คุณ mw ฉัน sd libc.so.6 7f97a4099000 r--p 001bc000 08:03 264328 352 4 4 64 1 64 0 0 0 64 0 0 0 0 0 0 0 0 0 0 0 0 rd mr mw ฉัน sd libc.so.6 7f97a40f1000 ---p 00214000 08:03 264328 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 mr mw ฉัน sd libc.so.6 7f97a40f2000 r--p 00214000 08:03 264328 16 4 4 16 16 0 0 16 16 16 0 0 0 0 0 0 0 0 0 0 0 rd นาย mw ฉัน ac sd libc.so.6 7f97a40f6000 rw-p 00218000 08:03 264328 8 4 4 8 8 0 0 0 8 8 8 0 0 0 0 0 0 0 0 0 0 0 rd wr mr mw me ac sd libc.so.6 7f97a40f8000 rw-p 00000000 00:00 0 60 4 4 28 28 0 0 0 28 28 28 0 0 0 0 0 0 0 0 0 0 0 rd wr นาย mw ฉัน ac sd 7f97a4116000 r--p 00000000 08:03 264305 4 4 4 4 0 4 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 rd mr mw ฉัน dw sd ld-linux-x86-64.so.2 7f97a4117000 r-xp 00001000 08:03 264305 160 4 4 160 11 160 0 0 160 0 0 0 0 0 0 0 0 0 0 0 0 rd อดีต คุณ mw ฉัน dw sd ld-linux-x86-64.so.2 7f97a413f000 r--p 00029000 08:03 264305 40 4 4 40 1 40 0 0 40 0 0 0 0 0 0 0 0 0 0 0 0 0 rd mr mw ฉัน dw sd ld-linux-x86-64.so.2 7f97a4149000 r--p 00032000 08:03 264305 8 4 4 8 8 0 0 0 8 8 8 0 0 0 0 0 0 0 0 0 0 0 rd mr mw ฉัน dw ac sd ld-linux-x86-64.so.2 7f97a414b000 rw-p 00034000 08:03 264305 8 4 4 8 8 0 0 0 8 8 8 0 0 0 0 0 0 0 0 0 0 0 rd wr mr mw ฉัน dw ac sd ld-linux-x86-64.so.2 7ffca0e7e000 rw-p 00000000 00:00 0 132 4 4 12 12 0 0 0 12 12 12 0 0 0 0 0 0 0 0 0 0 0 rd wr mr mw me gd ac [stack] 7ffca0fe1000 r--p 00000000 00:00 0 16 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 rd mr pf io de dd sd [vvar] 7ffca0fe5000 r-xp 00000000 00:00 0 8 4 4 0 4 0 0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 rd อดีต mr mw ฉัน de sd [vdso] ffffffffff600000 --xp 00000000 00:00 0 4 4 4 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 อดีต [vsyscall] ==== ============== ========== ==== === ============ == ========== ============= ============ ========== ==== ===== ======== ============= ============= ========== === ============== =================== ======= ====== = ========== 2756 92 92 1328 157 1220 0 12 96 1328 96 0 0 0 0 0 0 0 0 0 0 0 KB
มีข้อมูลมากมายที่นี่ นี่คือสิ่งที่คอลัมน์ถือ:
- ที่อยู่ : ที่อยู่เริ่มต้นของการทำแผนที่นี้ สิ่งนี้ใช้การกำหนดที่อยู่หน่วยความจำเสมือน
- Perm : การอนุญาตของหน่วยความจำ
- ออฟเซ็ ต : หากหน่วยความจำเป็นแบบไฟล์ ออฟเซ็ตของการแมปนี้ภายในไฟล์
- อุปกรณ์ : หมายเลขอุปกรณ์ Linux ที่ระบุเป็นตัวเลขหลักและรอง คุณสามารถดูหมายเลขอุปกรณ์บนคอมพิวเตอร์ของคุณได้โดยเรียกใช้คำสั่ง
lsblk
- Inode : ไอโหนดของไฟล์ที่เชื่อมโยงอยู่ ตัวอย่างเช่น ในตัวอย่างของเรา นี่อาจเป็นไอโหนดที่เก็บข้อมูลเกี่ยวกับโปรแกรม pm
- ขนาด : ขนาดของพื้นที่ที่แมปหน่วยความจำ
- KernelPageSize : ขนาดหน้าที่เคอร์เนลใช้
- MMUPageSize : ขนาดหน้าที่ใช้โดยหน่วยจัดการหน่วยความจำ
- Rss : นี่คือ ขนาดชุดที่อยู่อาศัย นั่นคือจำนวนหน่วยความจำที่อยู่ใน RAM และไม่มีการสลับออก
- Pss : นี่คือ ขนาดการแบ่งปันตามสัดส่วน นี่คือขนาดที่ใช้ร่วมกันส่วนตัวที่เพิ่มลงใน (ขนาดที่แชร์หารด้วยจำนวนการแชร์)
- Shared_Clean : จำนวนหน่วยความจำที่แบ่งใช้กับกระบวนการอื่นที่ ไม่ได้ เปลี่ยนแปลงตั้งแต่สร้างการแมป โปรดทราบว่าแม้ว่าหน่วยความจำจะแชร์ได้ แต่หากไม่ได้แชร์หน่วยความจำจริงจะยังถือเป็นหน่วยความจำส่วนตัว
- Shared_Dirty : จำนวนหน่วยความจำที่แชร์กับกระบวนการอื่นที่ มี การเปลี่ยนแปลงตั้งแต่สร้างการแมป
- Private_Clean : จำนวนหน่วยความจำส่วนตัว—ไม่ได้แชร์กับกระบวนการอื่น—ซึ่ง ไม่มี การเปลี่ยนแปลงตั้งแต่สร้างการแมป
- Private_Dirty : จำนวนหน่วยความจำส่วนตัวที่ มี การเปลี่ยนแปลงตั้งแต่สร้างการแมป
- อ้างอิง : จำนวนหน่วยความจำที่ทำเครื่องหมายว่าอ้างอิงหรือเข้าถึงในปัจจุบัน
- Anonymous : หน่วยความจำที่ไม่มีอุปกรณ์ให้สลับไปใช้ นั่นคือมันไม่ได้สำรองไฟล์
- LazyFree : เพจที่ถูกตั้งค่าสถานะเป็น
MADV_FREE
หน้าเหล่านี้ถูกทำเครื่องหมายว่าว่างและเรียกคืนได้ แม้ว่าหน้าเหล่านี้อาจมีการเปลี่ยนแปลงที่ไม่ได้เขียนเป็นลายลักษณ์อักษรก็ตาม อย่างไรก็ตาม หากการเปลี่ยนแปลงที่ตามมาเกิดขึ้นหลังจากตั้งค่าMADV_FREE
ในการแมปหน่วยความจำ แฟMADV_FREE
จะถูกลบออก และเพจจะไม่ถูกเรียกคืนจนกว่าจะมีการเขียนการเปลี่ยนแปลง - AnonHugePages : เป็นเพจหน่วยความจำ “ขนาดใหญ่” ที่ไม่ได้สำรองไฟล์ไว้ (ขนาดใหญ่กว่า 4 KB)
- ShmemPmdMapped : หน่วยความจำที่ใช้ร่วมกันที่เกี่ยวข้องกับเพจขนาดใหญ่ ระบบไฟล์เหล่านี้อาจใช้โดยระบบไฟล์ที่อยู่ในหน่วยความจำทั้งหมด
- FilePmdMapped : Page Middle Directory เป็นหนึ่งในรูปแบบการเพจที่มีให้สำหรับเคอร์เนล นี่คือจำนวนหน้าที่สำรองไฟล์ซึ่งชี้ไปที่รายการ PMD
- Shared_Hugetlb : Translation Lookaside Tables หรือ TLBs เป็นแคชหน่วยความจำที่ใช้ในการปรับเวลาที่ใช้ในการเข้าถึงตำแหน่งหน่วยความจำ userspace ให้เหมาะสม ตัวเลขนี้คือจำนวน RAM ที่ใช้ใน TLB ที่เชื่อมโยงกับเพจหน่วยความจำขนาดใหญ่ที่ใช้ร่วมกัน
- Private_Hugetlb : ตัวเลขนี้คือจำนวน RAM ที่ใช้ใน TLB ที่เชื่อมโยงกับหน้าหน่วยความจำส่วนตัวขนาดใหญ่
- Swap : จำนวนสวอปที่ใช้
- SwapPss : ขนาดหุ้นตามสัดส่วนการสวอป นี่คือจำนวนสวอปที่ประกอบด้วยเพจหน่วยความจำส่วนตัวที่สลับที่เพิ่มไปยัง (ขนาดที่แบ่งใช้หารด้วยจำนวนการแชร์)
- ล็อค : สามารถล็อคการแมปหน่วยความจำเพื่อป้องกันไม่ให้ระบบปฏิบัติการเพจออกจากหน่วยความจำฮีปหรือหน่วยความจำนอกฮีป
- THมีสิทธิ์ : นี่คือแฟล็กที่ระบุว่าการแมปมีสิทธิ์ในการจัดสรร เพจขนาดใหญ่ที่โปร่งใส หรือไม่ 1 หมายถึง จริง 0 หมายถึง เท็จ เพจขนาดใหญ่แบบโปร่งใสคือระบบจัดการหน่วยความจำที่ช่วยลดโอเวอร์เฮดของการค้นหาเพจ TLB บนคอมพิวเตอร์ที่มี RAM จำนวนมาก
- VmFlags : ดูรายการแฟล็กด้านล่าง
- การทำแผนที่ : ชื่อของแหล่งที่มาของการทำแผนที่ ซึ่งอาจเป็นชื่อกระบวนการ ชื่อไลบรารี หรือชื่อระบบ เช่น สแต็กหรือฮีป
VmFlags—แฟล็กหน่วยความจำเสมือน—จะเป็นชุดย่อยของรายการต่อไปนี้
- rd : อ่านได้
- wr : เขียนได้.
- ตัวอย่าง : ปฏิบัติการได้
- sh : แชร์
- นาย : เมย์อ่านะ
- mw : อาจเขียน.
- ฉัน : อาจประหารชีวิต
- ms : อาจแบ่งปัน.
- gd : ส่วนกองโตขึ้น
- pf : ช่วงหมายเลขเฟรมหน้าล้วน หมายเลขเฟรมหน้าคือรายการของหน้าหน่วยความจำกายภาพ
- dw : ปิดการใช้งานเขียนไปยังไฟล์ที่แมป
- แท้จริง : เพจถูกล็อคในหน่วยความจำ
- io : พื้นที่ I/O ที่แมปหน่วยความจำ
- sr : ให้อ่านคำแนะนำตามลำดับ (โดย
madvise()
) - rr : สุ่มอ่านคำแนะนำที่ให้ไว้
- dc : อย่าคัดลอกขอบเขตหน่วยความจำนี้หากกระบวนการถูกแยก
- de : อย่าขยายขอบเขตหน่วยความจำนี้ในการทำการแมปใหม่
- ac : พื้นที่รับผิดชอบ
- nr : พื้นที่สว็อปไม่ได้สงวนไว้สำหรับพื้นที่นั้น
- ht : Area ใช้หน้า TLB ขนาดใหญ่
- sf : ความผิดพลาดของเพจแบบซิงโครนัส
- ar : แฟล็กเฉพาะสถาปัตยกรรม
- wf : เช็ดพื้นที่หน่วยความจำนี้หากกระบวนการถูกแยก
- dd : ไม่รวมขอบเขตหน่วยความจำนี้ใน core dumps
- sd : ธงสกปรกนุ่ม
- มม. : พื้นที่แผนที่ผสม
- hg : หน้าใหญ่แนะนำแฟล็ก
- nh : ไม่มีเพจขนาดใหญ่แนะนำแฟล็ก
- mg : แฟล็กคำแนะนำที่ผสานได้
- bt : ARM64 หน้าป้องกันความไม่เสถียรของอุณหภูมิอคติ
- mt : เปิดใช้งานแท็กส่วนขยายการติดแท็กหน่วยความจำ ARM64
- um : Userfaultfd ไม่มีการติดตาม
- uw : การติดตาม Userfaultfd wr-protect
การจัดการหน่วยความจำมีความซับซ้อน
และการทำงานย้อนกลับจากตารางข้อมูลเพื่อทำความเข้าใจกับสิ่งที่เกิดขึ้นจริงนั้นยาก แต่อย่างน้อย pmap
จะให้ภาพรวมแก่คุณ เพื่อให้คุณมีโอกาสที่ดีที่สุดในการค้นหาสิ่งที่คุณต้องรู้
เป็นเรื่องที่น่าสนใจที่จะสังเกตว่าโปรแกรมตัวอย่างของเราคอมไพล์เป็นไฟล์ปฏิบัติการไบนารีขนาด 16 KB แต่ก็ยังใช้ (หรือแชร์) หน่วยความจำบางส่วน 2756 KB เกือบทั้งหมดเนื่องจากไลบรารีรันไทม์
เคล็ดลับสุดท้ายที่เรียบร้อยอย่างหนึ่งคือ คุณสามารถใช้ pmap
และคำสั่ง pidof
ร่วมกัน โดยรวมการดำเนินการในการค้นหา PID ของกระบวนการและส่งผ่านไปยัง pmap
เป็นคำสั่งเดียว:
pmap $(pidof pm)