Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 The Chromium Authors. All rights reserved. | 2 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # A Python library to read and store procfs (/proc) information on Linux. | 6 # A Python library to read and store procfs (/proc) information on Linux. |
| 7 # | 7 # |
| 8 # Each information storage class in this file stores original data as original | 8 # Each information storage class in this file stores original data as original |
| 9 # as reasonablly possible. Translation is done when requested. It is to make it | 9 # as reasonablly possible. Translation is done when requested. It is to make it |
| 10 # always possible to probe the original data. | 10 # always possible to probe the original data. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 def load_file(stat_f): | 85 def load_file(stat_f): |
| 86 raw = stat_f.readlines() | 86 raw = stat_f.readlines() |
| 87 stat = ProcStat._PATTERN.match(raw[0]) | 87 stat = ProcStat._PATTERN.match(raw[0]) |
| 88 return ProcStat(raw, | 88 return ProcStat(raw, |
| 89 stat.groupdict().get('PID'), | 89 stat.groupdict().get('PID'), |
| 90 stat.groupdict().get('VSIZE'), | 90 stat.groupdict().get('VSIZE'), |
| 91 stat.groupdict().get('RSS')) | 91 stat.groupdict().get('RSS')) |
| 92 | 92 |
| 93 @staticmethod | 93 @staticmethod |
| 94 def load(pid): | 94 def load(pid): |
| 95 with open(os.path.join('/proc', str(pid), 'stat'), 'r') as stat_f: | 95 try: |
| 96 return ProcStat.load_file(stat_f) | 96 with open(os.path.join('/proc', str(pid), 'stat'), 'r') as stat_f: |
| 97 return ProcStat.load_file(stat_f) | |
| 98 except IOError: | |
| 99 return None | |
| 97 | 100 |
| 98 @property | 101 @property |
| 99 def raw(self): | 102 def raw(self): |
| 100 return self._raw | 103 return self._raw |
| 101 | 104 |
| 102 @property | 105 @property |
| 103 def pid(self): | 106 def pid(self): |
| 104 return int(self._pid) | 107 return int(self._pid) |
| 105 | 108 |
| 106 @property | 109 @property |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 128 self._size = size | 131 self._size = size |
| 129 self._resident = resident | 132 self._resident = resident |
| 130 self._share = share | 133 self._share = share |
| 131 self._text = text | 134 self._text = text |
| 132 self._lib = lib | 135 self._lib = lib |
| 133 self._data = data | 136 self._data = data |
| 134 self._dt = dt | 137 self._dt = dt |
| 135 | 138 |
| 136 @staticmethod | 139 @staticmethod |
| 137 def load_file(statm_f): | 140 def load_file(statm_f): |
| 138 raw = statm_f.readlines() | 141 try: |
| 142 raw = statm_f.readlines() | |
| 143 except (IOError, OSError): | |
|
peria
2013/12/09 05:08:13
You use two styles to catch multiple-type exceptio
| |
| 144 return None | |
| 139 statm = ProcStatm._PATTERN.match(raw[0]) | 145 statm = ProcStatm._PATTERN.match(raw[0]) |
| 140 return ProcStatm(raw, | 146 return ProcStatm(raw, |
| 141 statm.groupdict().get('SIZE'), | 147 statm.groupdict().get('SIZE'), |
| 142 statm.groupdict().get('RESIDENT'), | 148 statm.groupdict().get('RESIDENT'), |
| 143 statm.groupdict().get('SHARE'), | 149 statm.groupdict().get('SHARE'), |
| 144 statm.groupdict().get('TEXT'), | 150 statm.groupdict().get('TEXT'), |
| 145 statm.groupdict().get('LIB'), | 151 statm.groupdict().get('LIB'), |
| 146 statm.groupdict().get('DATA'), | 152 statm.groupdict().get('DATA'), |
| 147 statm.groupdict().get('DT')) | 153 statm.groupdict().get('DT')) |
| 148 | 154 |
| 149 @staticmethod | 155 @staticmethod |
| 150 def load(pid): | 156 def load(pid): |
| 151 with open(os.path.join('/proc', str(pid), 'statm'), 'r') as statm_f: | 157 try: |
| 152 return ProcStatm.load_file(statm_f) | 158 with open(os.path.join('/proc', str(pid), 'statm'), 'r') as statm_f: |
| 159 return ProcStatm.load_file(statm_f) | |
| 160 except (IOError, OSError): | |
| 161 return None | |
| 153 | 162 |
| 154 @property | 163 @property |
| 155 def raw(self): | 164 def raw(self): |
| 156 return self._raw | 165 return self._raw |
| 157 | 166 |
| 158 @property | 167 @property |
| 159 def size(self): | 168 def size(self): |
| 160 return int(self._size) | 169 return int(self._size) |
| 161 | 170 |
| 162 @property | 171 @property |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 323 | 332 |
| 324 @staticmethod | 333 @staticmethod |
| 325 def load_file(maps_f): | 334 def load_file(maps_f): |
| 326 table = ProcMaps() | 335 table = ProcMaps() |
| 327 for line in maps_f: | 336 for line in maps_f: |
| 328 table.append_line(line) | 337 table.append_line(line) |
| 329 return table | 338 return table |
| 330 | 339 |
| 331 @staticmethod | 340 @staticmethod |
| 332 def load(pid): | 341 def load(pid): |
| 333 with open(os.path.join('/proc', str(pid), 'maps'), 'r') as maps_f: | 342 try: |
| 334 return ProcMaps.load_file(maps_f) | 343 with open(os.path.join('/proc', str(pid), 'maps'), 'r') as maps_f: |
| 344 return ProcMaps.load_file(maps_f) | |
| 345 except IOError: | |
| 346 return None | |
| 347 except OSError: | |
| 348 return None | |
| 335 | 349 |
| 336 def append_line(self, line): | 350 def append_line(self, line): |
| 337 entry = self.parse_line(line) | 351 entry = self.parse_line(line) |
| 338 if entry: | 352 if entry: |
| 339 self._append_entry(entry) | 353 self._append_entry(entry) |
| 340 return entry | 354 return entry |
| 341 | 355 |
| 342 @staticmethod | 356 @staticmethod |
| 343 def parse_line(line): | 357 def parse_line(line): |
| 344 matched = ProcMaps.MAPS_PATTERN.match(line) | 358 matched = ProcMaps.MAPS_PATTERN.match(line) |
| (...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 548 | 562 |
| 549 @staticmethod | 563 @staticmethod |
| 550 def load(pid, maps): | 564 def load(pid, maps): |
| 551 total_present = 0 | 565 total_present = 0 |
| 552 total_swapped = 0 | 566 total_swapped = 0 |
| 553 total_vsize = 0 | 567 total_vsize = 0 |
| 554 in_process_dup = 0 | 568 in_process_dup = 0 |
| 555 vma_internals = collections.OrderedDict() | 569 vma_internals = collections.OrderedDict() |
| 556 process_pageframe_set = set() | 570 process_pageframe_set = set() |
| 557 | 571 |
| 558 pagemap_fd = os.open( | 572 try: |
| 559 os.path.join('/proc', str(pid), 'pagemap'), os.O_RDONLY) | 573 pagemap_fd = os.open( |
| 574 os.path.join('/proc', str(pid), 'pagemap'), os.O_RDONLY) | |
| 575 except IOError: | |
| 576 return None | |
| 577 except OSError: | |
| 578 return None | |
| 560 for vma in maps: | 579 for vma in maps: |
| 561 present = 0 | 580 present = 0 |
| 562 swapped = 0 | 581 swapped = 0 |
| 563 vsize = 0 | 582 vsize = 0 |
| 564 pageframes = collections.defaultdict(int) | 583 pageframes = collections.defaultdict(int) |
| 565 begin_offset = ProcPagemap._offset(vma.begin) | 584 begin_offset = ProcPagemap._offset(vma.begin) |
| 566 chunk_size = ProcPagemap._offset(vma.end) - begin_offset | 585 chunk_size = ProcPagemap._offset(vma.end) - begin_offset |
| 567 os.lseek(pagemap_fd, begin_offset, os.SEEK_SET) | 586 try: |
| 568 buf = os.read(pagemap_fd, chunk_size) | 587 os.lseek(pagemap_fd, begin_offset, os.SEEK_SET) |
| 588 buf = os.read(pagemap_fd, chunk_size) | |
| 589 except IOError: | |
| 590 return None | |
| 591 except OSError: | |
| 592 return None | |
| 569 if len(buf) < chunk_size: | 593 if len(buf) < chunk_size: |
| 570 _LOGGER.warn('Failed to read pagemap at 0x%x in %d.' % (vma.begin, pid)) | 594 _LOGGER.warn('Failed to read pagemap at 0x%x in %d.' % (vma.begin, pid)) |
| 571 pagemap_values = struct.unpack( | 595 pagemap_values = struct.unpack( |
| 572 '=%dQ' % (len(buf) / ProcPagemap._BYTES_PER_PAGEMAP_VALUE), buf) | 596 '=%dQ' % (len(buf) / ProcPagemap._BYTES_PER_PAGEMAP_VALUE), buf) |
| 573 for pagemap_value in pagemap_values: | 597 for pagemap_value in pagemap_values: |
| 574 vsize += ProcPagemap._BYTES_PER_OS_PAGE | 598 vsize += ProcPagemap._BYTES_PER_OS_PAGE |
| 575 if pagemap_value & ProcPagemap._MASK_PRESENT: | 599 if pagemap_value & ProcPagemap._MASK_PRESENT: |
| 576 if (pagemap_value & ProcPagemap._MASK_PFN) in process_pageframe_set: | 600 if (pagemap_value & ProcPagemap._MASK_PFN) in process_pageframe_set: |
| 577 in_process_dup += ProcPagemap._BYTES_PER_OS_PAGE | 601 in_process_dup += ProcPagemap._BYTES_PER_OS_PAGE |
| 578 else: | 602 else: |
| 579 process_pageframe_set.add(pagemap_value & ProcPagemap._MASK_PFN) | 603 process_pageframe_set.add(pagemap_value & ProcPagemap._MASK_PFN) |
| 580 if (pagemap_value & ProcPagemap._MASK_PFN) not in pageframes: | 604 if (pagemap_value & ProcPagemap._MASK_PFN) not in pageframes: |
| 581 present += ProcPagemap._BYTES_PER_OS_PAGE | 605 present += ProcPagemap._BYTES_PER_OS_PAGE |
| 582 pageframes[pagemap_value & ProcPagemap._MASK_PFN] += 1 | 606 pageframes[pagemap_value & ProcPagemap._MASK_PFN] += 1 |
| 583 if pagemap_value & ProcPagemap._MASK_SWAPPED: | 607 if pagemap_value & ProcPagemap._MASK_SWAPPED: |
| 584 swapped += ProcPagemap._BYTES_PER_OS_PAGE | 608 swapped += ProcPagemap._BYTES_PER_OS_PAGE |
| 585 vma_internals[vma] = ProcPagemap.VMA(vsize, present, swapped, pageframes) | 609 vma_internals[vma] = ProcPagemap.VMA(vsize, present, swapped, pageframes) |
| 586 total_present += present | 610 total_present += present |
| 587 total_swapped += swapped | 611 total_swapped += swapped |
| 588 total_vsize += vsize | 612 total_vsize += vsize |
| 589 os.close(pagemap_fd) | 613 try: |
| 614 os.close(pagemap_fd) | |
| 615 except OSError: | |
| 616 return None | |
| 590 | 617 |
| 591 return ProcPagemap(total_vsize, total_present, total_swapped, | 618 return ProcPagemap(total_vsize, total_present, total_swapped, |
| 592 vma_internals, in_process_dup) | 619 vma_internals, in_process_dup) |
| 593 | 620 |
| 594 @staticmethod | 621 @staticmethod |
| 595 def _offset(virtual_address): | 622 def _offset(virtual_address): |
| 596 return virtual_address / ProcPagemap._VIRTUAL_TO_PAGEMAP_OFFSET | 623 return virtual_address / ProcPagemap._VIRTUAL_TO_PAGEMAP_OFFSET |
| 597 | 624 |
| 598 @property | 625 @property |
| 599 def vsize(self): | 626 def vsize(self): |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 720 print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024, | 747 print ' status: %d (Peak:%d)' % (procs[pid].status.vm_rss * 1024, |
| 721 procs[pid].status.vm_hwm * 1024) | 748 procs[pid].status.vm_hwm * 1024) |
| 722 print ' smaps: %d' % (procs[pid].smaps.rss * 1024) | 749 print ' smaps: %d' % (procs[pid].smaps.rss * 1024) |
| 723 print 'pagemap: %d' % procs[pid].pagemap.present | 750 print 'pagemap: %d' % procs[pid].pagemap.present |
| 724 | 751 |
| 725 return 0 | 752 return 0 |
| 726 | 753 |
| 727 | 754 |
| 728 if __name__ == '__main__': | 755 if __name__ == '__main__': |
| 729 sys.exit(main(sys.argv)) | 756 sys.exit(main(sys.argv)) |
| OLD | NEW |