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 |