|
| 1 | +WeChat: cstutorcs |
| 2 | +QQ: 749389476 |
| 3 | +Email: tutorcs@163.com |
| 4 | +#include <iostream> |
| 5 | +#include <vector> |
| 6 | + |
| 7 | +// This is a simplified version of the Linux kernel's memory management: mm_types.h |
| 8 | +// You can find the original file at: https://elixir.bootlin.com/linux/v6.4.11/source/include/linux/mm_types.h |
| 9 | + |
| 10 | + |
| 11 | +// Define the Page structure to track individual pages |
| 12 | +struct page { |
| 13 | + bool pte_present; // A flag to indicate if the page is in memory or swapped |
| 14 | + bool pte_young; // A flag to indicate if the page is in use |
| 15 | + std::string data; // Name or data associated with the page |
| 16 | +}; |
| 17 | + |
| 18 | +// Define the vm_area_struct structure (simplified for illustration) |
| 19 | +struct vm_area_struct { |
| 20 | + unsigned long vm_start; // Start address of the VMA |
| 21 | + unsigned long vm_end; // End address of the VMA |
| 22 | + std::vector <page> pages; // A list of pages in the VMA |
| 23 | +}; |
| 24 | + |
| 25 | +// Define a mm_struct structure (simplified for illustration) |
| 26 | +struct mm_struct { |
| 27 | + std::vector <vm_area_struct> vma_list; // A list of VMAs |
| 28 | +}; |
| 29 | + |
| 30 | +struct vma_iterator { |
| 31 | + std::vector <vm_area_struct> vma_list; // A list of VMAs |
| 32 | + size_t index; // Index to track the current VMA |
| 33 | +}; |
| 34 | + |
| 35 | +// Define a macro to initialize the vma_iterator |
| 36 | +#define VMA_ITERATOR(name, __mm, __addr) \ |
| 37 | + struct vma_iterator name = { \ |
| 38 | + .vma_list = (__mm).vma_list, \ |
| 39 | + .index = __addr \ |
| 40 | + } |
| 41 | + |
| 42 | +// Function to get the next VMA |
| 43 | +vm_area_struct *vma_next(vma_iterator *vmi) { |
| 44 | + if (vmi->index < vmi->vma_list.size()) { |
| 45 | + return &vmi->vma_list[vmi->index++]; |
| 46 | + } else { |
| 47 | + return nullptr; |
| 48 | + } |
| 49 | +} |
| 50 | + |
| 51 | +// Define a macro to iterate through VMAs |
| 52 | +#define for_each_vma(__vmi, __vma) \ |
| 53 | + while (((__vma) = vma_next(&(__vmi))) != NULL) |
| 54 | + |
| 55 | +int main() { |
| 56 | + // Example usage |
| 57 | + mm_struct mm; |
| 58 | + struct vm_area_struct *vma = NULL; |
| 59 | + |
| 60 | + // Populate mm with some VMAs for demonstration |
| 61 | + vm_area_struct vma1 = { |
| 62 | + 0x1000, |
| 63 | + 0x3000, |
| 64 | + { |
| 65 | + {true, true, "Page 1"}, |
| 66 | + {false, false, "Page 2"}, |
| 67 | + {true, false, "Page 3"}, |
| 68 | + {true, true, "Page 4"}, |
| 69 | + {false, false, "Page 5"} |
| 70 | + } |
| 71 | + }; |
| 72 | + |
| 73 | + vm_area_struct vma2 = { |
| 74 | + 0x4000, |
| 75 | + 0x6000, |
| 76 | + { |
| 77 | + {true, false, "Page 6"}, |
| 78 | + {false, false, "Page 7"}, |
| 79 | + {true, true, "Page 8"}, |
| 80 | + {true, false, "Page 9"}, |
| 81 | + {true, true, "Page 10"} |
| 82 | + } |
| 83 | + }; |
| 84 | + |
| 85 | + mm.vma_list.push_back(vma1); |
| 86 | + mm.vma_list.push_back(vma2); |
| 87 | + |
| 88 | + // Initialize memory statistics variables |
| 89 | + unsigned long total_rss = 0; |
| 90 | + unsigned long total_swap = 0; |
| 91 | + unsigned long total_wss = 0; |
| 92 | + |
| 93 | + // TODO 1: Use mm_struct to initialize the VMA_ITERATOR |
| 94 | + // Hint: Use the VMA_ITERATOR macro, and initialize the index to 0 |
| 95 | + // Hint: Use the mm_struct to access the list of VMAs |
| 96 | + // Hint: Only one line of code is needed |
| 97 | + |
| 98 | + |
| 99 | + // TODO 2: Replace the while loop with for_each_vma macro |
| 100 | + // Hint: Use the for_each_vma macro to iterate through the VMAs |
| 101 | + // Hint: Only one line of code is needed, then remove the while loop |
| 102 | + while (1) { |
| 103 | + // Initialize VMA statistics variables |
| 104 | + unsigned long vma_rss = 0; |
| 105 | + unsigned long vma_swap = 0; |
| 106 | + unsigned long vma_wss = 0; |
| 107 | + |
| 108 | + // TODO 3: Iterate through the pages in the VMA and update the memory statistics |
| 109 | + // Hint: Use the page structure to access individual pages |
| 110 | + // Hint: Use the vma_rss, vma_swap, and vma_wss variables to track the memory statistics |
| 111 | + // Hint: if pte_present is true, the page is in memory; otherwise, it is swapped |
| 112 | + // Hint: if pte_young is true, the page is in use |
| 113 | + // Hint: Only about 10 lines of code are needed |
| 114 | + |
| 115 | + |
| 116 | + // Update the memory statistics for the entire process |
| 117 | + total_rss += vma_rss; |
| 118 | + total_swap += vma_swap; |
| 119 | + total_wss += vma_wss; |
| 120 | + |
| 121 | + // Print memory statistics for the VMA |
| 122 | + std::cout << std::endl; |
| 123 | + std::cout << "VMA: " << vma->vm_start << " - " << vma->vm_end << std::endl; |
| 124 | + std::cout << " Resident Set Size: " << vma_rss << std::endl; |
| 125 | + std::cout << " Swapped Size: " << vma_swap << std::endl; |
| 126 | + std::cout << " Working Set Size: " << vma_wss << std::endl; |
| 127 | + } |
| 128 | + |
| 129 | + // Print memory statistics for the entire process |
| 130 | + std::cout << std::endl; |
| 131 | + std::cout << "Memory Statistics:" << std::endl; |
| 132 | + std::cout << " Total Resident Set Size: " << total_rss << std::endl; |
| 133 | + std::cout << " Total Swapped Size: " << total_swap << std::endl; |
| 134 | + std::cout << " Total Working Set Size: " << total_wss << std::endl; |
| 135 | + |
| 136 | + return 0; |
| 137 | +} |
0 commit comments